]> source.dussan.org Git - aspectj.git/commitdiff
Work on Bugzilla 42668: effect of an after returning type incompatible with a join...
authorehilsdal <ehilsdal>
Tue, 18 Nov 2003 02:43:31 +0000 (02:43 +0000)
committerehilsdal <ehilsdal>
Tue, 18 Nov 2003 02:43:31 +0000 (02:43 +0000)
 * fix to semantics document to describe correct semantics
 * checkin of failing coverage test case for correct semantics

docs/progGuideDB/semantics.xml
tests/ajcTestsFailing.xml
tests/bugs/IncompatibleAfterReturningTypeCE.java [deleted file]
tests/ehTests.xml [new file with mode: 0644]
tests/new/AfterReturningParamMatching.java [new file with mode: 0644]

index 6e8f8f649155a1793a7043d802d74952efa78098..639ddeb9b19d10c42b99bd3b39ef06b0f7ca3fc8 100644 (file)
 </programlisting>
 
     <para>
-      It is an error to try to put after returning advice on a join point that
-      does not return the correct type.  For example,
+      If after returning does expose its returned object, then the
+      type of the parameter is considered to be an
+      <literal>instanceof</literal>-like constraint on the advice:  it
+      will run only when the return value is of the appropriate type.
     </para>
 
-<programlisting>
-  after() returning (byte b): call(int String.length()) {
-      // this is an error
-  }
-</programlisting>
+    <para>
+      A value is of the appropriate type if it would be assignable to
+      a variable of that type, in the Java sense.
+      <literal>byte</literal>, <literal>short</literal>,
+      <literal>char</literal> and <literal>int</literal> are
+      assignable to each other, an <literal>int</literal> is
+      assignable to a <literal>float</literal> parameter,
+      <literal>boolean</literal> values are only assignable to
+      <literal>boolean</literal> parameters, and reference types work
+      by instanceof. 
+    </para>
+
+    <para>
+      There are two special cases: If the exposed value is typed to
+      <literal>Object</literal>, then the advice is not constrained by
+      that type: the actual return value is converted to an object
+      type for the body of the advice: <literal>int</literal> values
+      are represented as <literal>java.lang.Integer</literal> objects,
+      etc, and no value (from void methods, for example) is
+      represented as <literal>null</literal>.
+    </para>
 
     <para>
-      is not allowed.  But if no return value is exposed, or the exposed return
-      value is typed to <literal>Object</literal>, then it may be applied to
-      any join point.  If the exposed value is typed to
-      <literal>Object</literal>, then the actual return value is converted to
-      an object type for the body of the advice:  <literal>int</literal> values
-      are represented as <literal>java.lang.Integer</literal> objects, etc, and
-      no value (from void methods, for example) is represented as
-      <literal>null</literal>.
+      Secondly, the <literal>null</literal> value is assignable to a
+      parameter <literal>T</literal> if the join point
+      <emphasis>could</emphasis> return something of type
+      <literal>T</literal>.
     </para>
 
     <para>
index c021e9451438f527789ee3ca42063a247bf7bb16..fe3fdc6649f61dc32ad6f113273ea0a5d540cd32 100644 (file)
                <run class="packageProtected.concern.BaseTarget"/>
                </ajc-test>
                
-       <ajc-test dir="bugs"
-               title="after returning type incompatible with join point return type"
-               pr="42668"
-               >
-               <compile files="IncompatibleAfterReturningTypeCE.java">
-                       <message kind="error" line="20"/>
-                       <message kind="error" line="22"/>
-                       </compile>
-               </ajc-test>
-               
        <ajc-test dir="bugs"
                pr="41888"
                title="call PCD fails when given subtype of defining type">
                files="Main.java"/>
         <run class="Main"/>
     </ajc-test>
+    
+    <ajc-test dir="new" 
+     pr="42668"
+        title="after returning with parameter: matching rules">
+        <compile files="AfterReturningParamMatching.java" />
+        <run class="AfterReturningParamMatching"/>
+    </ajc-test>
+
 
 </suite>
diff --git a/tests/bugs/IncompatibleAfterReturningTypeCE.java b/tests/bugs/IncompatibleAfterReturningTypeCE.java
deleted file mode 100644 (file)
index d935d34..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-
-public class IncompatibleAfterReturningTypeCE {
-    public static void main(String[] args) {
-        System.setProperty("foo", ""+"".length());
-    }
-}
-
-class C {
-    Integer getInteger() { 
-        return null;
-    }
-}
-
-/** @testcase PR#42668 after returning type incompatible with join point return type */
-aspect A {
-
-    after () returning (Boolean b) : execution(Integer C.getInteger()) { } // CE 20 incompatible return type from join point    
-
-    after () returning (byte b) : call(int String.length()) {} // CE 22 incompatible return type 
-
-}
\ No newline at end of file
diff --git a/tests/ehTests.xml b/tests/ehTests.xml
new file mode 100644 (file)
index 0000000..da5ae28
--- /dev/null
@@ -0,0 +1,10 @@
+
+<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd">
+
+<suite>
+    <ajc-test dir="new" pr="42668"
+        title="after returning with parameter: matching rules">
+        <compile files="AfterReturningParamMatching.java" />
+        <run class="AfterReturningParamMatching"/>
+    </ajc-test>
+</suite>  
\ No newline at end of file
diff --git a/tests/new/AfterReturningParamMatching.java b/tests/new/AfterReturningParamMatching.java
new file mode 100644 (file)
index 0000000..062bfa5
--- /dev/null
@@ -0,0 +1,72 @@
+import org.aspectj.testing.Tester;
+
+// this test verifies the matching behaivor for after returning with a typed parameter.
+
+public class AfterReturningParamMatching {
+       public static void main(String[] args) {
+               goBoolean(false);
+               Tester.checkAndClearEvents(new String[] { "Object" });
+
+               goByte(1);
+               Tester.checkAndClearEvents(new String[] { "byte", "int", "long", "Object"});
+               
+               goInt(2);
+               Tester.checkAndClearEvents(new String[] { "byte", "int", "long", "Object" });
+
+               goLong(3);
+               Tester.checkAndClearEvents(new String[] { "byte", "int", "long", "Object" });
+               
+               goObject(new Object());
+               Tester.checkAndClearEvents(new String[] { "Object" });
+               
+           goObject(new Integer(4));
+               Tester.checkAndClearEvents(new String[] { "Object", "Number", "Integer" });
+               
+               goObject(null); 
+               Tester.checkAndClearEvents(new String[] { "Object" });
+           
+               goNumber(new Long(5));
+               Tester.checkAndClearEvents(new String[] { "Object", "Number" });
+               
+               goNumber(new Integer(6));
+               Tester.checkAndClearEvents(new String[] { "Object", "Number", "Integer" });
+
+               goNumber(null);
+               Tester.checkAndClearEvents(new String[] { "Object", "Number" });
+
+               goInteger(new Integer(7));
+               Tester.checkAndClearEvents(new String[] { "Object", "Number", "Integer" });
+
+        goInteger(null);
+        Tester.checkAndClearEvents(new String[] { "Object", "Number", "Integer" });
+
+       }
+       static boolean goBoolean(boolean b) { return b; }
+       static byte goByte(int i) { return (byte) i; }
+       static int goInt(int i) { return i; }
+       static long goLong(int i) { return (long) i; }
+       
+       static Object goObject(Object o) { return o; }
+       static Number goNumber(Number o) { return o; }
+       static Integer goInteger(Integer o) { return o; }
+}
+
+aspect A {
+       
+       pointcut methodsInQuestion():
+               call(* goBoolean(*)) || 
+               call(* goByte(*)) || 
+               call(* goInt(*)) || 
+               call(* goLong(*)) || 
+               call(* goObject(*)) || 
+               call(* goNumber(*)) || 
+               call(* goInteger(*)); 
+       
+       after() returning(byte b): methodsInQuestion() { Tester.event("byte"); }
+       after() returning(int b): methodsInQuestion() { Tester.event("int"); }
+       after() returning(long b): methodsInQuestion() { Tester.event("long"); }
+       after() returning(Object b): methodsInQuestion() { Tester.event("Object"); }
+       after() returning(Number b): methodsInQuestion() { Tester.event("Number"); }
+       after() returning(Integer b): methodsInQuestion() { Tester.event("Integer"); }
+
+}
\ No newline at end of file