7153951: Add new lint option -Xlint:auxiliaryclass
authorohrstrom
Thu, 01 Nov 2012 10:48:36 +0100
changeset 14369 3d660d08d1f7
parent 14368 6f4c62de6985
child 14370 eefd0e6642a8
7153951: Add new lint option -Xlint:auxiliaryclass Reviewed-by: jjg, mcimadamore, forax
langtools/src/share/classes/com/sun/tools/javac/code/Flags.java
langtools/src/share/classes/com/sun/tools/javac/code/Lint.java
langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java
langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
langtools/test/tools/javac/diags/examples/AuxiliaryClassWarning/ClassUsingAuxiliary.java
langtools/test/tools/javac/diags/examples/AuxiliaryClassWarning/ClassWithAuxiliary.java
langtools/test/tools/javac/warnings/AuxiliaryClass/ClassUsingAnotherAuxiliary.java
langtools/test/tools/javac/warnings/AuxiliaryClass/ClassUsingAnotherAuxiliary.out
langtools/test/tools/javac/warnings/AuxiliaryClass/ClassUsingAuxiliary.java
langtools/test/tools/javac/warnings/AuxiliaryClass/ClassUsingAuxiliary1.out
langtools/test/tools/javac/warnings/AuxiliaryClass/ClassUsingAuxiliary2.out
langtools/test/tools/javac/warnings/AuxiliaryClass/ClassWithAuxiliary.java
langtools/test/tools/javac/warnings/AuxiliaryClass/NotAClassName.java
langtools/test/tools/javac/warnings/AuxiliaryClass/SelfClassWithAux.java
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Wed Oct 31 13:48:15 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Thu Nov 01 10:48:36 2012 +0100
@@ -258,6 +258,12 @@
      */
     public static final long DEFAULT = 1L<<43;
 
+    /**
+     * Flag that marks class as auxiliary, ie a non-public class following
+     * the public class in a source file, that could block implicit compilation.
+     */
+    public static final long AUXILIARY = 1L<<43;
+
     /** Modifier masks.
      */
     public static final int
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java	Wed Oct 31 13:48:15 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java	Thu Nov 01 10:48:36 2012 +0100
@@ -129,6 +129,13 @@
      */
     public enum LintCategory {
         /**
+         * Warn when code refers to a auxiliary class that is hidden in a source file (ie source file name is
+         * different from the class name, and the type is not properly nested) and the referring code
+         * is not located in the same source file.
+         */
+        AUXILIARYCLASS("auxiliaryclass"),
+
+        /**
          * Warn about use of unnecessary casts.
          */
         CAST("cast"),
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Oct 31 13:48:15 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Nov 01 10:48:36 2012 +0100
@@ -3050,6 +3050,7 @@
                 // except for two situations:
                 owntype = sym.type;
                 if (owntype.hasTag(CLASS)) {
+                    chk.checkForBadAuxiliaryClassAccess(tree.pos(), env, (ClassSymbol)sym);
                     Type ownOuter = owntype.getEnclosingType();
 
                     // (a) If the symbol's type is parameterized, erase it
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Wed Oct 31 13:48:15 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Nov 01 10:48:36 2012 +0100
@@ -27,6 +27,7 @@
 
 import java.util.*;
 import java.util.Set;
+import javax.tools.JavaFileManager;
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.jvm.*;
@@ -77,6 +78,7 @@
     private boolean suppressAbortOnBadClassFile;
     private boolean enableSunApiLintControl;
     private final TreeInfo treeinfo;
+    private final JavaFileManager fileManager;
 
     // The set of lint options currently in effect. It is initialized
     // from the context, and then is set/reset as needed by Attr as it
@@ -109,6 +111,7 @@
         Options options = Options.instance(context);
         lint = Lint.instance(context);
         treeinfo = TreeInfo.instance(context);
+        fileManager = context.get(JavaFileManager.class);
 
         Source source = Source.instance(context);
         allowGenerics = source.allowGenerics();
@@ -3230,6 +3233,19 @@
             return true;
         }
 
+    /** Check that an auxiliary class is not accessed from any other file than its own.
+     */
+    void checkForBadAuxiliaryClassAccess(DiagnosticPosition pos, Env<AttrContext> env, ClassSymbol c) {
+        if (lint.isEnabled(Lint.LintCategory.AUXILIARYCLASS) &&
+            (c.flags() & AUXILIARY) != 0 &&
+            rs.isAccessible(env, c) &&
+            !fileManager.isSameFile(c.sourcefile, env.toplevel.sourcefile))
+        {
+            log.warning(pos, "auxiliary.class.accessed.from.outside.of.its.source.file",
+                        c, c.sourcefile);
+        }
+    }
+
     private class ConversionWarner extends Warner {
         final String uncheckedKey;
         final Type found;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Wed Oct 31 13:48:15 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Thu Nov 01 10:48:36 2012 +0100
@@ -1022,11 +1022,13 @@
             // name as a top-level package.
             if (checkClash &&
                 c.owner.kind == PCK && c.owner != syms.unnamedPackage &&
-                reader.packageExists(c.fullname))
-                {
-                    log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c);
-                }
-
+                reader.packageExists(c.fullname)) {
+                log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c);
+            }
+            if (c.owner.kind == PCK && (c.flags_field & PUBLIC) == 0 &&
+                !env.toplevel.sourcefile.isNameCompatible(c.name.toString(),JavaFileObject.Kind.SOURCE)) {
+                c.flags_field |= AUXILIARY;
+            }
         } catch (CompletionFailure ex) {
             chk.completionError(tree.pos(), ex);
         } finally {
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Wed Oct 31 13:48:15 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Thu Nov 01 10:48:36 2012 +0100
@@ -1018,6 +1018,15 @@
                     ClassSymbol c = (ClassSymbol) sym;
                     Name n = readName(nextChar());
                     c.sourcefile = new SourceFileObject(n, c.flatname);
+                    // If the class is a toplevel class, originating from a Java source file,
+                    // but the class name does not match the file name, then it is
+                    // an auxiliary class.
+                    String sn = n.toString();
+                    if (c.owner.kind == Kinds.PCK &&
+                        sn.endsWith(".java") &&
+                        !sn.equals(c.name.toString()+".java")) {
+                        c.flags_field |= AUXILIARY;
+                    }
                 }
             },
 
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Oct 31 13:48:15 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Nov 01 10:48:36 2012 +0100
@@ -1847,6 +1847,11 @@
 
 #####
 
+# 0: type, 1: file name
+compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file=\
+    auxiliary class {0} in {1} should not be accessed from outside its own source file
+
+
 ## The first argument ({0}) is a "kindname".
 # 0: symbol kind, 1: symbol, 2: symbol
 compiler.err.abstract.cant.be.accessed.directly=\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/AuxiliaryClassWarning/ClassUsingAuxiliary.java	Thu Nov 01 10:48:36 2012 +0100
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+// key: compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file
+// options: -Xlint:auxiliaryclass
+
+class ClassUsingAuxiliary {
+    AuxiliaryClass ahem;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/AuxiliaryClassWarning/ClassWithAuxiliary.java	Thu Nov 01 10:48:36 2012 +0100
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+class ClassWithAuxiliaryClass {
+}
+
+// Auxiliary class that cannot be found through implicit compilation.
+class AuxiliaryClass {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/AuxiliaryClass/ClassUsingAnotherAuxiliary.java	Thu Nov 01 10:48:36 2012 +0100
@@ -0,0 +1,34 @@
+/*
+ * 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
+ * @compile ClassUsingAnotherAuxiliary.java NotAClassName.java
+ * @compile -Xlint:auxiliaryclass ClassUsingAnotherAuxiliary.java NotAClassName.java
+ * @compile/fail/ref=ClassUsingAnotherAuxiliary.out -XDrawDiagnostics -Werror -Xlint:auxiliaryclass ClassUsingAnotherAuxiliary.java NotAClassName.java
+ */
+
+class ClassUsingAnotherAuxiliary {
+    AnAuxiliaryClass ahem;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/AuxiliaryClass/ClassUsingAnotherAuxiliary.out	Thu Nov 01 10:48:36 2012 +0100
@@ -0,0 +1,4 @@
+ClassUsingAnotherAuxiliary.java:32:5: compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file: AnAuxiliaryClass, NotAClassName.java
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/AuxiliaryClass/ClassUsingAuxiliary.java	Thu Nov 01 10:48:36 2012 +0100
@@ -0,0 +1,34 @@
+/*
+ * 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
+ * @clean ClassUsingAuxiliary ClassWithAuxiliary AuxiliaryClass ClassWithAuxiliary$NotAnAuxiliaryClass ClassWithAuxiliary$NotAnAuxiliaryClassEither
+ * @run compile ClassUsingAuxiliary.java ClassWithAuxiliary.java
+ * @run compile/fail/ref=ClassUsingAuxiliary1.out -XDrawDiagnostics -Werror -Xlint:auxiliaryclass ClassUsingAuxiliary.java ClassWithAuxiliary.java
+ * @run compile/fail/ref=ClassUsingAuxiliary2.out -XDrawDiagnostics -Werror -Xlint:auxiliaryclass ClassUsingAuxiliary.java
+ */
+
+class ClassUsingAuxiliary {
+    AuxiliaryClass ahem;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/AuxiliaryClass/ClassUsingAuxiliary1.out	Thu Nov 01 10:48:36 2012 +0100
@@ -0,0 +1,4 @@
+ClassUsingAuxiliary.java:33:5: compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file: AuxiliaryClass, ClassWithAuxiliary.java
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/AuxiliaryClass/ClassUsingAuxiliary2.out	Thu Nov 01 10:48:36 2012 +0100
@@ -0,0 +1,4 @@
+ClassUsingAuxiliary.java:33:5: compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file: AuxiliaryClass, ClassWithAuxiliary.java
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/AuxiliaryClass/ClassWithAuxiliary.java	Thu Nov 01 10:48:36 2012 +0100
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+public class ClassWithAuxiliary {
+    public static class NotAnAuxiliaryClass { }
+    public class NotAnAuxiliaryClassEither { }
+}
+
+// Auxiliary class that cannot be found through implicit compilation.
+class AuxiliaryClass {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/AuxiliaryClass/NotAClassName.java	Thu Nov 01 10:48:36 2012 +0100
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+class AnAuxiliaryClass {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/AuxiliaryClass/SelfClassWithAux.java	Thu Nov 01 10:48:36 2012 +0100
@@ -0,0 +1,44 @@
+/*
+ * 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 that an auxiliary class referenced from its own source file,
+ * does not trigger the warning. Such code does not prevent implicit
+ * compilation. Also test that references to inner classes do not trigger the warning.
+ */
+
+/*
+ * @test
+ * @run compile -Werror -Xlint:auxiliaryclass SelfClassWithAux.java ClassWithAuxiliary.java
+ * @run compile -Werror -Xlint:auxiliaryclass SelfClassWithAux.java
+ */
+
+class SelfClassWithAux {
+    Aux aux;
+    ClassWithAuxiliary.NotAnAuxiliaryClass alfa;
+    ClassWithAuxiliary.NotAnAuxiliaryClassEither beta;
+}
+
+class Aux {
+    Aux aux;
+}