changeset 1703:4014132b136e

Enhancement: Add experimental support for private (instance) interface methods Note: there's no JVM support for this feature for the time being. Some examples might be made to work using -Xverify:none.
author mcimadamore
date Mon, 17 Dec 2012 17:53:09 +0000
parents 1f2fbcd0de7e
children b11f5172a066
files src/share/classes/com/sun/tools/javac/code/Flags.java src/share/classes/com/sun/tools/javac/code/Source.java src/share/classes/com/sun/tools/javac/comp/Check.java src/share/classes/com/sun/tools/javac/parser/JavacParser.java src/share/classes/com/sun/tools/javac/resources/compiler.properties test/tools/javac/defaultMethods/private/Private01.java test/tools/javac/defaultMethods/syntax/TestDefaultMethodsSyntax.java test/tools/javac/diags/examples.not-yet.txt
diffstat 8 files changed, 84 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/Flags.java	Mon Dec 17 15:36:20 2012 +0000
+++ b/src/share/classes/com/sun/tools/javac/code/Flags.java	Mon Dec 17 17:53:09 2012 +0000
@@ -281,7 +281,7 @@
                                 SYNCHRONIZED | FINAL | STRICTFP;
     public static final long
         ExtendedStandardFlags       = (long)StandardFlags | DEFAULT,
-        InterfaceMethodMask         = ABSTRACT | STATIC | PUBLIC | STRICTFP | SYNCHRONIZED | DEFAULT,
+        InterfaceMethodMask         = ABSTRACT | PRIVATE | STATIC | PUBLIC | STRICTFP | SYNCHRONIZED | DEFAULT,
         LocalVarFlags               = FINAL | PARAMETER;
 
 
--- a/src/share/classes/com/sun/tools/javac/code/Source.java	Mon Dec 17 15:36:20 2012 +0000
+++ b/src/share/classes/com/sun/tools/javac/code/Source.java	Mon Dec 17 17:53:09 2012 +0000
@@ -209,6 +209,9 @@
     public boolean allowStaticInterfaceMethods() {
         return compareTo(JDK1_8) >= 0;
     }
+    public boolean allowPrivateInterfaceMethods() {
+        return compareTo(JDK1_8) >= 0;
+    }
     public boolean allowStrictMethodClashCheck() {
         return compareTo(JDK1_8) >= 0;
     }
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Dec 17 15:36:20 2012 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Dec 17 17:53:09 2012 +0000
@@ -1045,9 +1045,9 @@
                 } else
                     mask = ConstructorFlags;
             }  else if ((sym.owner.flags_field & INTERFACE) != 0) {
-                if ((flags & (DEFAULT | STATIC)) != 0) {
+                if ((flags & (DEFAULT | STATIC | PRIVATE)) != 0) {
                     mask = InterfaceMethodMask;
-                    implicit = PUBLIC;
+                    implicit = (flags & PRIVATE) != 0 ? 0 : PUBLIC;
                     if ((flags & DEFAULT) != 0) {
                         implicit |= ABSTRACT;
                     }
@@ -1124,6 +1124,14 @@
                                 DEFAULT)
                  &&
                  checkDisjoint(pos, flags,
+                                PRIVATE,
+                                DEFAULT)
+                 &&
+                 (sym.kind == TYP || (sym.owner.flags_field & INTERFACE) == 0 || checkDisjoint(pos, flags,
+                                PRIVATE,
+                                STATIC))
+                 &&
+                 checkDisjoint(pos, flags,
                                ABSTRACT | INTERFACE,
                                FINAL | NATIVE | SYNCHRONIZED)
                  &&
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Dec 17 15:36:20 2012 +0000
+++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Dec 17 17:53:09 2012 +0000
@@ -127,6 +127,7 @@
         this.allowMethodReferences = source.allowMethodReferences();
         this.allowDefaultMethods = source.allowDefaultMethods();
         this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
+        this.allowPrivateInterfaceMethods = source.allowPrivateInterfaceMethods();
         this.allowIntersectionTypesInCast =
                 source.allowIntersectionTypesInCast();
         this.keepDocComments = keepDocComments;
@@ -205,6 +206,10 @@
     /** Switch: should we allow static methods in interfaces?
      */
     boolean allowStaticInterfaceMethods;
+    
+    /** Switch: should we allow private (instance) methods in interfaces?
+     */
+    boolean allowPrivateInterfaceMethods;
 
     /** Switch: should we allow intersection types in cast?
      */
@@ -3099,6 +3104,9 @@
         if (isInterface && mods.getFlags().contains(Modifier.STATIC)) {
             checkStaticInterfaceMethods();
         }
+        if (isInterface && mods.getFlags().contains(Modifier.PRIVATE)) {
+            checkPrivateInterfaceMethods();
+        }
         List<JCVariableDecl> params = formalParameters();
         if (!isVoid) type = bracketsOpt(type);
         List<JCExpression> thrown = List.nil();
@@ -3494,6 +3502,12 @@
             allowStaticInterfaceMethods = true;
         }
     }
+    void checkPrivateInterfaceMethods() {
+        if (!allowStaticInterfaceMethods) {
+            log.error(token.pos, "private.intf.methods.not.supported.in.source", source.name);
+            allowStaticInterfaceMethods = true;
+        }
+    }
     void checkIntersectionTypesInCast() {
         if (!allowIntersectionTypesInCast) {
             log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name);
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Dec 17 15:36:20 2012 +0000
+++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Dec 17 17:53:09 2012 +0000
@@ -2213,6 +2213,11 @@
     (use -source 8 or higher to enable static interface methods)
 
 # 0: string
+compiler.err.private.intf.methods.not.supported.in.source=\
+    private interface methods are not supported in -source {0}\n\
+    (use -source 8 or higher to enable private interface methods)
+
+# 0: string
 compiler.err.intersection.types.in.cast.not.supported.in.source=\
     intersection types in cast are not supported in -source {0}\n\
     (use -source 8 or higher to enable default methods)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/defaultMethods/private/Private01.java	Mon Dec 17 17:53:09 2012 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary smoke test for private interface methods featuring accessor methods
+ * @compile Private01.java
+ */
+public class Private01 {
+    interface P {
+        private void foo() { System.out.println("foo!" + this); }
+        default void m() {
+           new Object() { void test() { foo(); } }.test();
+        }
+    }
+
+    public static void main(String[] args) {
+        P p = new P() {};
+        p.m(); p.foo();
+    }
+}
--- a/test/tools/javac/defaultMethods/syntax/TestDefaultMethodsSyntax.java	Mon Dec 17 15:36:20 2012 +0000
+++ b/test/tools/javac/defaultMethods/syntax/TestDefaultMethodsSyntax.java	Mon Dec 17 17:53:09 2012 +0000
@@ -87,7 +87,8 @@
         static boolean compatible(MethodKind mk, ModifierKind mod1, ModifierKind mod2, EnclosingKind ek) {
             if (intersect(ABSTRACT, mod1, mod2) || intersect(NATIVE, mod1, mod2)) {
                 return mk == MethodKind.NO_BODY;
-            } else if (intersect(DEFAULT, mod1, mod2) || intersect(STATIC, mod1, mod2)) {
+            } else if (intersect(DEFAULT, mod1, mod2) || intersect(STATIC, mod1, mod2)
+                    || intersect(PRIVATE, mod1, mod2)) {
                 return mk == MethodKind.BODY;
             } else {
                 return ek == EnclosingKind.INTERFACE ?
@@ -97,7 +98,6 @@
 
         boolean compatible(EnclosingKind ek) {
             switch (this) {
-                case PRIVATE:
                 case PROTECTED:
                     return ek != EnclosingKind.INTERFACE;
                 default:
@@ -149,16 +149,16 @@
 
         static Result[][] allowedModifierPairs = {
             /*                     NONE  PUBLIC  PROTECTED  PRIVATE  ABSTRACT  STATIC  NATIVE  SYNCHRONIZED  FINAL  STRICTFP  DEFAULT */
-            /* NONE */           { T   , T    , C        , C       , T       , T     , C     , C           , C    , C       , I   },
+            /* NONE */           { T   , T    , C        , T       , T       , T     , C     , C           , C    , C       , I   },
             /* PUBLIC */         { T   , F    , F        , F       , T       , T     , C     , C           , C    , C       , I   },
             /* PROTECTED */      { C   , F    , F        , F       , C       , C     , C     , C           , C    , C       , F   },
-            /* PRIVATE */        { C   , F    , F        , F       , F       , C     , C     , C           , C    , C       , F   },
+            /* PRIVATE */        { T   , F    , F        , F       , F       , C     , C     , T           , C    , T       , F   },
             /* ABSTRACT */       { T   , T    , C        , F       , F       , F     , F     , F           , F    , F       , F   },
             /* STATIC */         { T   , T    , C        , C       , F       , F     , C     , T           , C    , T       , F   },
             /* NATIVE */         { C   , C    , C        , C       , F       , C     , F     , C           , C    , F       , F   },
-            /* SYNCHRONIZED */   { C   , C    , C        , C       , F       , T     , C     , F           , C    , C       , I   },
+            /* SYNCHRONIZED */   { C   , C    , C        , T       , F       , T     , C     , F           , C    , C       , I   },
             /* FINAL */          { C   , C    , C        , C       , F       , C     , C     , C           , F    , C       , F   },
-            /* STRICTFP */       { C   , C    , C        , C       , F       , T     , F     , C           , C    , F       , I   },
+            /* STRICTFP */       { C   , C    , C        , T       , F       , T     , F     , C           , C    , F       , I   },
             /* DEFAULT */        { I   , I    , F        , F       , F       , F     , F     , I           , F    , I       , F   }};
     }
 
@@ -266,6 +266,9 @@
 
         errorExpected |= ModifierKind.intersect(ModifierKind.STATIC, modk1, modk2) &&
                 ek == EnclosingKind.INTERFACE && vk == VersionKind.PRE_LAMBDA;
+        
+        errorExpected |= ModifierKind.intersect(ModifierKind.PRIVATE, modk1, modk2) &&
+                ek == EnclosingKind.INTERFACE && vk == VersionKind.PRE_LAMBDA;
 
         checkCount++;
         if (diagChecker.errorFound != errorExpected) {
--- a/test/tools/javac/diags/examples.not-yet.txt	Mon Dec 17 15:36:20 2012 +0000
+++ b/test/tools/javac/diags/examples.not-yet.txt	Mon Dec 17 17:53:09 2012 +0000
@@ -109,3 +109,4 @@
 compiler.warn.unknown.enum.constant                     # in bad class file
 compiler.warn.unknown.enum.constant.reason              # in bad class file
 compiler.err.static.intf.methods.not.supported.in.source                         #LAMBDA
+compiler.err.private.intf.methods.not.supported.in.source                        #LAMBDA
\ No newline at end of file