changeset 2957:171268c46d77

interim fix for handling different modules in package parent chain
author jjg
date Tue, 31 Mar 2015 13:15:40 -0700
parents 17d1e0cb6083
children 92a298b8a0d7
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java test/tools/javac/modules/SubpackageTest.java
diffstat 8 files changed, 197 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java	Fri Mar 27 16:40:35 2015 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java	Tue Mar 31 13:15:40 2015 -0700
@@ -42,6 +42,7 @@
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.Completer;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.code.Symbol.TypeSymbol;
 import com.sun.tools.javac.comp.Annotate;
@@ -418,6 +419,9 @@
      *             is older.
      */
     protected void includeClassFile(PackageSymbol p, JavaFileObject file) {
+        if (p.modle == null && p.modleHint != null)
+            p.modle = p.modleHint;
+
         if ((p.flags_field & EXISTS) == 0)
             for (Symbol q = p; q != null && q.kind == PCK; q = q.owner)
                 q.flags_field |= EXISTS;
@@ -435,7 +439,7 @@
             ? p.package_info
             : (ClassSymbol) p.members_field.findFirst(classname);
         if (c == null) {
-            c = syms.enterClass(classname, p);
+            c = syms.enterClass(p.modle, classname, p);
             if (c.classfile == null) // only update the file if's it's newly created
                 c.classfile = file;
             if (isPkgInfo) {
@@ -500,9 +504,10 @@
         if (p.members_field == null)
             p.members_field = WriteableScope.create(p);
 
-        if (p.modle != null) { // TODO: This needs to become an assert
+        ModuleSymbol msym = (p.modle != null) ? p.modle : p.modleHint;
+        if (msym != null) { // TODO: This needs to become an assert
             // new code
-            if (p.modle == syms.noModule) {
+            if (msym == syms.noModule) {
                 preferCurrent = false;
                 if (userPathsFirst) {
                     scanUserPaths(p);
@@ -512,18 +517,18 @@
                     scanPlatformPath(p);
                     scanUserPaths(p);
                 }
-            } else if (p.modle.classLocation == StandardLocation.CLASS_PATH) {
+            } else if (msym.classLocation == StandardLocation.CLASS_PATH) {
                 // assert p.modle.sourceLocation == StandardLocation.SOURCE_PATH);
                 scanUserPaths(p);
             } else {
-                scanModulePaths(p);
+                scanModulePaths(p, msym);
             }
             return;
         }
 
         // old code, to go away
         if (p.modle != null && p.modle.classLocation != null) {
-            scanModulePaths(p);
+            scanModulePaths(p, p.modle);
         } else {
             preferCurrent = false;
             if (userPathsFirst) {
@@ -544,7 +549,7 @@
     // -classpath and -sourcepath for single module mode.
     // One plausible solution is to detect if the module's sourceLocation
     // is the same as the module's classLocation.
-    private void scanModulePaths(PackageSymbol p) throws IOException {
+    private void scanModulePaths(PackageSymbol p, ModuleSymbol msym) throws IOException {
         Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
 
         Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
@@ -555,8 +560,8 @@
         sourceKinds.remove(JavaFileObject.Kind.CLASS);
         boolean wantSourceFiles = !sourceKinds.isEmpty();
 
-        Location classLocn = p.modle.classLocation;
-        Location sourceLocn = p.modle.sourceLocation;
+        Location classLocn = msym.classLocation;
+        Location sourceLocn = msym.sourceLocation;
 
         String packageName = p.fullname.toString();
         if (wantClassFiles && (classLocn != null)) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Mar 27 16:40:35 2015 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Tue Mar 31 13:15:40 2015 -0700
@@ -901,6 +901,7 @@
         public Name fullname;
         public ClassSymbol package_info; // see bug 6443073
         public ModuleSymbol modle;
+        public ModuleSymbol modleHint;
 
         public PackageSymbol(Name name, Type type, Symbol owner) {
             super(PCK, 0, name, type, owner);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Fri Mar 27 16:40:35 2015 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Tue Mar 31 13:15:40 2015 -0700
@@ -556,6 +556,10 @@
      *  and owner and enter in `classes' unless already there.
      */
     public ClassSymbol enterClass(Name name, TypeSymbol owner) {
+        return enterClass(null, name, owner);
+    }
+
+    public ClassSymbol enterClass(ModuleSymbol msym, Name name, TypeSymbol owner) {
         Name flatname = TypeSymbol.formFlatName(name, owner);
         ClassSymbol c = classes.get(flatname);
         if (c == null) {
@@ -582,7 +586,11 @@
      * @return a newly created class symbol
      * @throws AssertionError if the class symbol already exists
      */
-    public ClassSymbol enterClass(Name flatName, JavaFileObject classFile) {
+//    public ClassSymbol enterClass(Name flatName, JavaFileObject classFile) {
+//        return enterClass(null, flatName, classFile);
+//    }
+
+    public ClassSymbol enterClass(ModuleSymbol msym, Name flatName, JavaFileObject classFile) {
         ClassSymbol cs = classes.get(flatName);
         if (cs != null) {
             String msg = Log.format("%s: completer = %s; class file = %s; source file = %s",
@@ -595,7 +603,9 @@
         Name packageName = Convert.packagePart(flatName);
         PackageSymbol owner = packageName.isEmpty()
                                 ? unnamedPackage
-                                : enterPackage(packageName);
+                                : enterPackage(msym, packageName);
+        if (owner != unnamedPackage && owner.modle == null && msym != null)
+            owner.modle = msym;
         cs = defineClass(Convert.shortName(flatName), owner);
         cs.classfile = classFile;
         classes.put(flatName, cs);
@@ -606,17 +616,21 @@
      *  and enter in `classes' unless already there.
      */
     public ClassSymbol enterClass(Name flatname) {
+        return enterClass(null, flatname);
+    }
+
+    public ClassSymbol enterClass(ModuleSymbol msym, Name flatname) {
         ClassSymbol c = classes.get(flatname);
         if (c == null)
-            return enterClass(flatname, (JavaFileObject)null);
+            return enterClass(msym, flatname, (JavaFileObject)null);
         else
             return c;
     }
 
     /** Check to see if a package exists, given its fully qualified name.
      */
-    public boolean packageExists(Name fullname) {
-        return enterPackage(fullname).exists();
+    public boolean packageExists(ModuleSymbol msym, Name fullname) {
+        return enterPackage(null, fullname).exists();
     }
 
     /** Make a package, given its fully qualified name.
@@ -627,11 +641,32 @@
             Assert.check(!fullname.isEmpty(), "rootPackage missing!");
             p = new PackageSymbol(
                     Convert.shortName(fullname),
-                    enterPackage(currModule, Convert.packagePart(fullname)));
-            p.modle = currModule;
+                    enterPackage(null, Convert.packagePart(fullname)));
             p.completer = initialCompleter;
             packages.put(fullname, p);
         }
+//        if (currModule != null) {
+//            if (p.modle == null) {
+//                p.modle = currModule;
+//            } else if (p.modle != currModule) {
+//                // TODO: changing module?
+//                System.err.println("Package: " + fullname
+//                        + " old:" + p.modle
+//                        + " new:" + currModule
+//                        + " types: " + (p.members_field == null ? "null" : p.getEnclosedElements().size()));
+//            }
+//        }
+        if (p.modle == null && currModule != null) {
+//            if (p.modleHint != currModule) {
+//                System.err.println("Package: " + fullname
+//                        + " old:" + p.modleHint
+//                        + " new: " + currModule
+//                        + " comp:" + p.completer);
+//            }
+            p.modleHint = currModule;
+            if (p.completer == null)
+                p.completer = initialCompleter;
+        }
         return p;
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Mar 27 16:40:35 2015 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Mar 31 13:15:40 2015 -0700
@@ -4221,6 +4221,9 @@
 
     public void visitProvides(JCProvides tree) {
         ModuleSymbol msym = env.toplevel.modle;
+
+//        syms.enterPackage(msym, Convert.packagePart(TreeInfo.fullName(tree.implName))).complete();
+
         Type st = attribType(tree.serviceName, env, syms.objectType);
         Type it = attribType(tree.implName, env, st);
         if (st.hasTag(CLASS) && it.hasTag(CLASS)) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java	Fri Mar 27 16:40:35 2015 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java	Tue Mar 31 13:15:40 2015 -0700
@@ -307,7 +307,7 @@
         } else {
             JCPackageDecl pd = tree.getPackage();
             if (pd != null) {
-                tree.packge = pd.packge = syms.enterPackage(TreeInfo.fullName(pd.pid));
+                tree.packge = pd.packge = syms.enterPackage(tree.modle, TreeInfo.fullName(pd.pid));
                 if (   pd.annotations.nonEmpty()
                     || pkginfoOpt == PkgInfo.ALWAYS
                     || tree.docComments != null) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Fri Mar 27 16:40:35 2015 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Tue Mar 31 13:15:40 2015 -0700
@@ -809,7 +809,7 @@
             // name as a top-level package.
             if (checkClash &&
                 sym.owner.kind == PCK && sym.owner != syms.unnamedPackage &&
-                syms.packageExists(sym.fullname)) {
+                syms.packageExists(env.toplevel.modle, sym.fullname)) {
                 log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), sym);
             }
             if (sym.owner.kind == PCK && (sym.flags_field & PUBLIC) == 0 &&
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Mar 27 16:40:35 2015 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Tue Mar 31 13:15:40 2015 -0700
@@ -151,6 +151,10 @@
      */
     protected Symbol currentOwner = null;
 
+    /** The module containing the class currently being read.
+     */
+    protected ModuleSymbol currentModule = null;
+
     /** The buffer containing the currently read class file.
      */
     byte[] buf = new byte[INITIAL_BUFFER_SIZE];
@@ -474,7 +478,7 @@
         // simplified to (buf[start] == '[')
         return (buf[start] == '[' || buf[start + len - 1] == ';')
             ? (Object)sigToType(buf, start, len)
-            : (Object)syms.enterClass(names.fromUtf(internalize(buf, start,
+            : (Object)enterClass(names.fromUtf(internalize(buf, start,
                                                            len)));
     }
 
@@ -667,7 +671,7 @@
             switch (c) {
 
             case ';': {         // end
-                ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer,
+                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                          startSbp,
                                                          sbp - startSbp));
 
@@ -681,7 +685,7 @@
             }
 
             case '<':           // generic arguments
-                ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer,
+                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                          startSbp,
                                                          sbp - startSbp));
                 outer = new ClassType(outer, sigToTypes('>'), t) {
@@ -744,7 +748,7 @@
             case '.':
                 //we have seen an enclosing non-generic class
                 if (outer != Type.noType) {
-                    t = syms.enterClass(names.fromUtf(signatureBuffer,
+                    t = enterClass(names.fromUtf(signatureBuffer,
                                                  startSbp,
                                                  sbp - startSbp));
                     outer = new ClassType(outer, List.<Type>nil(), t);
@@ -1461,7 +1465,7 @@
         int index = poolIdx[i];
         int length = getChar(index + 1);
         if (buf[index + length + 2] != ';')
-            return syms.enterClass(readName(i)).type;
+            return enterClass(readName(i)).type;
         return readType(i);
     }
 
@@ -2253,6 +2257,14 @@
         enterTypevars(sym.type);
     }
 
+    protected ClassSymbol enterClass(Name name) {
+        return syms.enterClass(currentModule, name);
+    }
+
+    protected ClassSymbol enterClass(Name name, TypeSymbol owner) {
+        return syms.enterClass(currentModule, name, owner);
+    }
+
     /** Read contents of a given class symbol `c'. Both external and internal
      *  versions of an inner class are read.
      */
@@ -2278,6 +2290,7 @@
                 throw badClassFile("class.file.wrong.class",
                                    self.flatname);
             }
+            currentModule = c.packge().modle;
         } else {
             c.flags_field = flags;
             // TODO: validate name
@@ -2291,16 +2304,13 @@
                     int start = utf8Index + 3;
                     Name modInfoName = names.fromUtf(internalize(buf, start, len));
                     if (c.owner.name == null) {
-//                        Name moduleName = Convert.packagePart(modInfoName);
-//                        c.owner.name = moduleName;
-//                        c.fullname = c.flatname = modInfoName;
                         syms.enterModule((ModuleSymbol) c.owner, Convert.packagePart(modInfoName));
                     } else {
                         // TODO: validate name
                     }
                 }
             }
-
+            currentModule = (ModuleSymbol) c.owner;
         }
 
         // class attributes must be read before class
@@ -2358,7 +2368,7 @@
             if (outer != null) { // we have a member class
                 if (name == names.empty)
                     name = names.one;
-                ClassSymbol member = syms.enterClass(name, outer);
+                ClassSymbol member = enterClass(name, outer);
                 if ((flags & STATIC) == 0) {
                     ((ClassType)member.type).setEnclosingType(outer.type);
                     if (member.erasure_field != null)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/SubpackageTest.java	Tue Mar 31 13:15:40 2015 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, 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
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build ToolBox ModuleTestBase
+ * @run main SubpackageTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class SubpackageTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        SubpackageTest t = new SubpackageTest();
+        t.runTests();
+    }
+
+    @Test // based on JDK-8075435
+    void testUnnamedModule(Path base) throws Exception {
+        Path libsrc = base.resolve("lib/src");
+        tb.writeJavaFiles(libsrc,
+            "package p; public class E extends Error { }");
+        Path libclasses = base.resolve("lib/classes");
+        Files.createDirectories(libclasses);
+        tb.new JavacTask()
+                .outdir(libclasses.toString())
+                .files(findJavaFiles(libsrc))
+                .run()
+                .writeAll();
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+            "package p.q;\n"
+            + "import p.E;\n"
+            + "class Test {\n"
+            + "  void m() { throw new E(); }\n"
+            + "}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .classpath(libclasses.toString())
+                .outdir(classes.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testSimpleMulti(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("mp"),
+                "module mp { exports p; }",
+                "package p; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("mpq"),
+                "module mpq { exports p.q; }",
+                "package p.q; public class C2 { }");
+        tb.writeJavaFiles(src.resolve("mpqr"),
+                "module mpqr { exports p.q.r; }",
+                "package p.q.r; public class C3 { }");
+        tb.writeJavaFiles(src.resolve("m"),
+                "module m {"
+                + "  requires mp;\n"
+                + "  requires mpq;\n"
+                + "  requires mpqr;\n"
+                + "}",
+                "package x;\n"
+                + "class C {\n"
+                + "  p.C1 c1;\n"
+                + "  p.q.C2 c2;\n"
+                + "  p.q.r.C3 c3;\n"
+                + "}");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src.toString())
+                .outdir(modules.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+}