From c2ee320e61977c59c9101849c29ef5aef3b1b059 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 12 Jul 2016 14:41:14 -0700 Subject: [PATCH 01/16] 8138725: Add options for Javadoc generation Reviewed-by: ksrini, bpatel, ahgross --- .../com/sun/source/util/DocTreePath.java | 2 +- .../com/sun/tools/doclint/Checker.java | 34 +- .../com/sun/tools/doclint/HtmlTag.java | 5 +- .../tools/javac/parser/DocCommentParser.java | 1 - .../sun/tools/javac/parser/JavacParser.java | 2 +- .../formats/html/ConfigurationImpl.java | 43 +- .../doclets/formats/html/HtmlDoclet.java | 2 + .../formats/html/markup/HtmlWriter.java | 7 +- .../internal/toolkit/AbstractDoclet.java | 2 + .../toolkit/builders/AbstractBuilder.java | 9 +- .../toolkit/resources/doclets.properties | 2 + .../internal/toolkit/util/FatalError.java | 39 + .../com/sun/tools/javadoc/main/DocEnv.java | 14 +- .../com/sun/tools/javadoc/main/DocImpl.java | 13 +- .../tools/javadoc/main/JavaScriptScanner.java | 1103 +++++++++++++++++ .../sun/tools/javadoc/main/RootDocImpl.java | 6 +- .../javadoc/resources/javadoc.properties | 2 + .../formats/html/ConfigurationImpl.java | 12 + .../html/resources/standard.properties | 3 + .../doclets/toolkit/AbstractDoclet.java | 9 +- .../doclets/toolkit/CommentUtils.java | 19 + .../doclets/toolkit/Configuration.java | 23 +- .../toolkit/builders/AbstractBuilder.java | 3 + .../toolkit/resources/doclets.properties | 4 + .../toolkit/util/JavaScriptScanner.java | 116 ++ .../util/UncheckedDocletException.java | 56 + .../internal/doclets/toolkit/util/Utils.java | 28 + .../jdk/javadoc/internal/tool/Messager.java | 2 +- langtools/test/Makefile | 4 +- .../jdk/javadoc/tool/TestScriptInComment.java | 313 +++++ .../test/tools/doclint/html/OtherTagsTest.out | 5 +- .../tools/javadoc/TestScriptInComment.java | 314 +++++ 32 files changed, 2165 insertions(+), 32 deletions(-) create mode 100644 langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/FatalError.java create mode 100644 langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavaScriptScanner.java create mode 100644 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/JavaScriptScanner.java create mode 100644 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/UncheckedDocletException.java create mode 100644 langtools/test/jdk/javadoc/tool/TestScriptInComment.java create mode 100644 langtools/test/tools/javadoc/TestScriptInComment.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreePath.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreePath.java index 2b61f4f386a..b4b96353d8d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreePath.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreePath.java @@ -98,7 +98,7 @@ public class DocTreePath implements Iterable { * @param t the DocCommentTree to create the path for. */ public DocTreePath(TreePath treePath, DocCommentTree t) { - this.treePath = Objects.requireNonNull(treePath); + this.treePath = treePath; this.docComment = Objects.requireNonNull(t); this.parent = null; this.leaf = t; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java index 811f710ab9f..e7907c4dffd 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java @@ -423,7 +423,16 @@ public class Checker extends DocTreePathScanner { break; case OTHER: - env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName); + switch (t) { + case SCRIPT: + // ", true), // script tag in Lower Case + UC("", true), // script tag in Upper Case + WS("< script >#ALERT", false, "-Xdoclint:none"), // script tag with invalid white space + SP("", true), // script tag with an attribute + ON("x", true), // event handler attribute + URI("x", true); // javascript URI + + /** + * Creates an HTML fragment to be injected into a template. + * @param text the HTML fragment to put into a doc comment or option. + * @param hasScript whether or not this fragment does contain legal JavaScript + * @param opts any additional options to be specified when javadoc is run + */ + Comment(String text, boolean hasScript, String... opts) { + this.text = text; + this.hasScript = hasScript; + this.opts = Arrays.asList(opts); + } + + final String text; + final boolean hasScript; + final List opts; + }; + + /** + * Representative samples of positions in which javadoc may find JavaScript. + * Each template contains a series of strings, which are written to files or inferred as options. + * The first source file implies a corresponding output file which should not be written + * if the comment contains JavaScript and JavaScript is not allowed. + */ + enum Template { + OVR(" overview #COMMENT ", "package p; public class C { }"), + PKGINFO("#COMMENT package p;", "package p; public class C { }"), + PKGHTML("#COMMENT package p;", "package p; public class C { }"), + CLS("package p; #COMMENT public class C { }"), + CON("package p; public class C { #COMMENT public C() { } }"), + FLD("package p; public class C { #COMMENT public int f; }"), + MTH("package p; public class C { #COMMENT public void m() { } }"), + TOP("-top", "lorem #COMMENT ipsum", "package p; public class C { }"), + HDR("-header", "lorem #COMMENT ipsum", "package p; public class C { }"), + FTR("-footer", "lorem #COMMENT ipsum", "package p; public class C { }"), + BTM("-bottom", "lorem #COMMENT ipsum", "package p; public class C { }"), + DTTL("-doctitle", "lorem #COMMENT ipsum", "package p; public class C { }"), + PHDR("-packagesheader", "lorem #COMMENT ipsum", "package p; public class C { }"); + + Template(String... args) { + opts = new ArrayList(); + sources = new ArrayList(); + int i = 0; + while (args[i].startsWith("-")) { + // all options being tested have a single argument that follow the option + opts.add(args[i++]); + opts.add(args[i++]); + } + while(i < args.length) { + sources.add(args[i++]); + } + } + + // groups: 1 or not; 2: package name; 3: class name + private final Pattern pat = + Pattern.compile("(?i)()?.*?(?:package ([a-z]+);.*?(?:class ([a-z]+).*)?)?"); + + /** + * Infer the file in which to write the given source. + * @param dir the base source directory + * @param src the source text + * @return the file in which the source should be written + */ + File getSrcFile(File srcDir, String src) { + String f; + Matcher m = pat.matcher(src); + if (!m.matches()) + throw new Error("match failed"); + if (m.group(3) != null) { + f = m.group(2) + "/" + m.group(3) + ".java"; + } else if (m.group(2) != null) { + f = m.group(2) + "/" + (m.group(1) == null ? "package-info.java" : "package.html"); + } else { + f = "overview.html"; + } + return new File(srcDir, f); + } + + /** + * Get the options to give to javadoc. + * @param srcDir the srcDir to use -overview is needed + * @return + */ + List getOpts(File srcDir) { + if (!opts.isEmpty()) { + return opts; + } else if (sources.get(0).contains("overview")) { + return Arrays.asList("-overview", getSrcFile(srcDir, sources.get(0)).getPath()); + } else { + return Collections.emptyList(); + } + } + + /** + * Gets the output file corresponding to the first source file. + * This file should not be written if the comment contains JavaScript and JavaScripot is + * not allowed. + * @param dir the base output directory + * @return the output file + */ + File getOutFile(File outDir) { + String f; + Matcher m = pat.matcher(sources.get(0)); + if (!m.matches()) + throw new Error("match failed"); + if (m.group(3) != null) { + f = m.group(2) + "/" + m.group(3) + ".html"; + } else if (m.group(2) != null) { + f = m.group(2) + "/package-summary.html"; + } else { + f = "overview-summary.html"; + } + return new File(outDir, f); + } + + final List opts; + final List sources; + }; + + enum Option { + OFF(null), + ON("--allow-script-in-comments"); + + Option(String text) { + this.text = text; + } + + final String text; + }; + + private PrintStream out = System.err; + + public void run() throws Exception { + int count = 0; + for (Template template: Template.values()) { + for (Comment comment: Comment.values()) { + for (Option option: Option.values()) { + if (test(template, comment, option)) { + count++; + } + } + } + } + + out.println(count + " test cases run"); + if (errors > 0) { + throw new Exception(errors + " errors occurred"); + } + } + + boolean test(Template template, Comment comment, Option option) throws IOException { + if (option == Option.ON && !comment.hasScript) { + // skip --allowScriptInComments if comment does not contain JavaScript + return false; + } + + String test = template + "-" + comment + "-" + option; + out.println("Test: " + test); + + File dir = new File(test); + dir.mkdirs(); + File srcDir = new File(dir, "src"); + File outDir = new File(dir, "out"); + + String alert = "alert(\"" + test + "\");"; + for (String src: template.sources) { + writeFile(template.getSrcFile(srcDir, src), + src.replace("#COMMENT", + "/** " + comment.text.replace("#ALERT", alert) + " **/")); + } + + List opts = new ArrayList(); + opts.add("-sourcepath"); + opts.add(srcDir.getPath()); + opts.add("-d"); + opts.add(outDir.getPath()); + if (option.text != null) + opts.add(option.text); + for (String opt: template.getOpts(srcDir)) { + opts.add(opt.replace("#COMMENT", comment.text.replace("#ALERT", alert))); + } + opts.addAll(comment.opts); + opts.add("-noindex"); // index not required; save time/space writing files + opts.add("p"); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = javadoc(opts, pw); + pw.close(); + String log = sw.toString(); + writeFile(new File(dir, "log.txt"), log); + + out.println("opts: " + opts); + out.println(" rc: " + rc); + out.println(" log:"); + out.println(log); + + String ERROR = "Use --allow-script-in-comment"; + File outFile = template.getOutFile(outDir); + + boolean expectErrors = comment.hasScript && (option == Option.OFF); + + if (expectErrors) { + check(rc != 0, "unexpected exit code: " + rc); + check(log.contains(ERROR), "expected error message not found"); + check(!outFile.exists(), "output file found unexpectedly"); + } else { + check(rc == 0, "unexpected exit code: " + rc); + check(!log.contains(ERROR), "error message found"); + check(outFile.exists(), "output file not found"); + } + + out.println(); + return true; + } + + int javadoc(List opts, PrintWriter pw) { + return jdk.javadoc.internal.tool.Main.execute(opts.toArray(new String[opts.size()]), pw); + } + + File writeFile(File f, String text) throws IOException { + f.getParentFile().mkdirs(); + FileWriter fw = new FileWriter(f); + try { + fw.write(text); + } finally { + fw.close(); + } + return f; + } + + void check(boolean cond, String errMessage) { + if (!cond) { + error(errMessage); + } + } + + void error(String message) { + out.println("Error: " + message); + errors++; + } + + int errors = 0; +} + diff --git a/langtools/test/tools/doclint/html/OtherTagsTest.out b/langtools/test/tools/doclint/html/OtherTagsTest.out index 6b36a015aec..6068dbc9eab 100644 --- a/langtools/test/tools/doclint/html/OtherTagsTest.out +++ b/langtools/test/tools/doclint/html/OtherTagsTest.out @@ -19,10 +19,7 @@ OtherTagsTest.java:20: error: element not allowed in documentation comments: * ^ -OtherTagsTest.java:22: error: element not allowed in documentation comments: - ^ OtherTagsTest.java:23: error: element not allowed in documentation comments: * <title> ^ -9 errors +8 errors diff --git a/langtools/test/tools/javadoc/TestScriptInComment.java b/langtools/test/tools/javadoc/TestScriptInComment.java new file mode 100644 index 00000000000..761887e573b --- /dev/null +++ b/langtools/test/tools/javadoc/TestScriptInComment.java @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2016, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 + * @bug 8138725 + * @summary test --allow-script-in-comments + * @modules jdk.javadoc/com.sun.tools.javadoc + */ + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Combo-style test, exercising combinations of different HTML fragments that may contain + * JavaScript, different places to place those fragments, and whether or not to allow the use + * of JavaScript. + */ +public class TestScriptInComment { + public static void main(String... args) throws Exception { + new TestScriptInComment().run(); + } + + /** + * Representative samples of different fragments of HTML that may contain JavaScript. + * To facilitate checking the output manually in a browser, the text "#ALERT" will be + * replaced by a JavaScript call of "alert(msg)", using a message string that is specific + * to the test case. + */ + enum Comment { + LC("", true), // script tag in Lower Case + UC("", true), // script tag in Upper Case + WS("< script >#ALERT", false, "-Xdoclint:none"), // script tag with invalid white space + SA("", true), // script tag with an attribute + ON("x", true), // event handler attribute + URI("x", true); // javadcript URI + + /** + * Creates an HTML fragment to be injected into a template. + * @param text the HTML fragment to put into a doc comment or option. + * @param hasScript whether or not this fragment does contain legal JavaScript + * @param opts any additional options to be specified when javadoc is run + */ + Comment(String text, boolean hasScript, String... opts) { + this.text = text; + this.hasScript = hasScript; + this.opts = Arrays.asList(opts); + } + + final String text; + final boolean hasScript; + final List opts; + }; + + /** + * Representative samples of positions in which javadoc may find JavaScript. + * Each template contains a series of strings, which are written to files or inferred as options. + * The first source file implies a corresponding output file which should not be written + * if the comment contains JavaScript and JavaScript is not allowed. + */ + enum Template { + OVR(" overview #COMMENT ", "package p; public class C { }"), + PKGINFO("#COMMENT package p;", "package p; public class C { }"), + PKGHTML("#COMMENT package p;", "package p; public class C { }"), + CLS("package p; #COMMENT public class C { }"), + CON("package p; public class C { #COMMENT public C() { } }"), + FLD("package p; public class C { #COMMENT public int f; }"), + MTH("package p; public class C { #COMMENT public void m() { } }"), + TOP("-top", "lorem #COMMENT ipsum", "package p; public class C { }"), + HDR("-header", "lorem #COMMENT ipsum", "package p; public class C { }"), + FTR("-footer", "lorem #COMMENT ipsum", "package p; public class C { }"), + BTM("-bottom", "lorem #COMMENT ipsum", "package p; public class C { }"), + DTTL("-doctitle", "lorem #COMMENT ipsum", "package p; public class C { }"), + PHDR("-packagesheader", "lorem #COMMENT ipsum", "package p; public class C { }"); + + Template(String... args) { + opts = new ArrayList(); + sources = new ArrayList(); + int i = 0; + while (args[i].startsWith("-")) { + // all options being tested have a single argument that follow the option + opts.add(args[i++]); + opts.add(args[i++]); + } + while(i < args.length) { + sources.add(args[i++]); + } + } + + // groups: 1 or not; 2: package name; 3: class name + private final Pattern pat = + Pattern.compile("(?i)()?.*?(?:package ([a-z]+);.*?(?:class ([a-z]+).*)?)?"); + + /** + * Infer the file in which to write the given source. + * @param dir the base source directory + * @param src the source text + * @return the file in which the source should be written + */ + File getSrcFile(File srcDir, String src) { + String f; + Matcher m = pat.matcher(src); + if (!m.matches()) + throw new Error("match failed"); + if (m.group(3) != null) { + f = m.group(2) + "/" + m.group(3) + ".java"; + } else if (m.group(2) != null) { + f = m.group(2) + "/" + (m.group(1) == null ? "package-info.java" : "package.html"); + } else { + f = "overview.html"; + } + return new File(srcDir, f); + } + + /** + * Get the options to give to javadoc. + * @param srcDir the srcDir to use -overview is needed + * @return + */ + List getOpts(File srcDir) { + if (!opts.isEmpty()) { + return opts; + } else if (sources.get(0).contains("overview")) { + return Arrays.asList("-overview", getSrcFile(srcDir, sources.get(0)).getPath()); + } else { + return Collections.emptyList(); + } + } + + /** + * Gets the output file corresponding to the first source file. + * This file should not be written if the comment contains JavaScript and JavaScripot is + * not allowed. + * @param dir the base output directory + * @return the output file + */ + File getOutFile(File outDir) { + String f; + Matcher m = pat.matcher(sources.get(0)); + if (!m.matches()) + throw new Error("match failed"); + if (m.group(3) != null) { + f = m.group(2) + "/" + m.group(3) + ".html"; + } else if (m.group(2) != null) { + f = m.group(2) + "/package-summary.html"; + } else { + f = "overview-summary.html"; + } + return new File(outDir, f); + } + + final List opts; + final List sources; + }; + + enum Option { + OFF(null), + ON("--allow-script-in-comments"); + + Option(String text) { + this.text = text; + } + + final String text; + }; + + private PrintStream out = System.err; + + public void run() throws Exception { + int count = 0; + for (Template template: Template.values()) { + for (Comment comment: Comment.values()) { + for (Option option: Option.values()) { + if (test(template, comment, option)) { + count++; + } + } + } + } + + out.println(count + " test cases run"); + if (errors > 0) { + throw new Exception(errors + " errors occurred"); + } + } + + boolean test(Template template, Comment comment, Option option) throws IOException { + if (option == Option.ON && !comment.hasScript) { + // skip --allowScriptInComments if comment does not contain JavaScript + return false; + } + + String test = template + "-" + comment + "-" + option; + out.println("Test: " + test); + + File dir = new File(test); + dir.mkdirs(); + File srcDir = new File(dir, "src"); + File outDir = new File(dir, "out"); + + String alert = "alert(\"" + test + "\");"; + for (String src: template.sources) { + writeFile(template.getSrcFile(srcDir, src), + src.replace("#COMMENT", + "/** " + comment.text.replace("#ALERT", alert) + " **/")); + } + + List opts = new ArrayList(); + opts.add("-sourcepath"); + opts.add(srcDir.getPath()); + opts.add("-d"); + opts.add(outDir.getPath()); + if (option.text != null) + opts.add(option.text); + for (String opt: template.getOpts(srcDir)) { + opts.add(opt.replace("#COMMENT", comment.text.replace("#ALERT", alert))); + } + opts.addAll(comment.opts); + opts.add("-noindex"); // index not required; save time/space writing files + opts.add("p"); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = javadoc(opts, pw); + pw.close(); + String log = sw.toString(); + writeFile(new File(dir, "log.txt"), log); + + out.println("opts: " + opts); + out.println(" rc: " + rc); + out.println(" log:"); + out.println(log); + + String ERROR = "Use --allow-script-in-comment"; + File outFile = template.getOutFile(outDir); + + boolean expectErrors = comment.hasScript && (option == Option.OFF); + + if (expectErrors) { + check(rc != 0, "unexpected exit code: " + rc); + check(log.contains(ERROR), "expected error message not found"); + check(!outFile.exists(), "output file found unexpectedly"); + } else { + check(rc == 0, "unexpected exit code: " + rc); + check(!log.contains(ERROR), "error message found"); + check(outFile.exists(), "output file not found"); + } + + out.println(); + return true; + } + + int javadoc(List opts, PrintWriter pw) { + return com.sun.tools.javadoc.Main.execute("javadoc", pw, pw, pw, + "com.sun.tools.doclets.standard.Standard", opts.toArray(new String[opts.size()])); + } + + File writeFile(File f, String text) throws IOException { + f.getParentFile().mkdirs(); + FileWriter fw = new FileWriter(f); + try { + fw.write(text); + } finally { + fw.close(); + } + return f; + } + + void check(boolean cond, String errMessage) { + if (!cond) { + error(errMessage); + } + } + + void error(String message) { + out.println("Error: " + message); + errors++; + } + + int errors = 0; +} + From 4873a69abe230227ce7fea231b92560cfd485036 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 17 Jan 2017 09:40:23 -0800 Subject: [PATCH 02/16] 8172686: Use less aggressive deprecation of utility visitors Reviewed-by: jjg, smarks --- .../lang/model/util/AbstractAnnotationValueVisitor6.java | 6 +++--- .../lang/model/util/AbstractAnnotationValueVisitor7.java | 2 +- .../javax/lang/model/util/AbstractElementVisitor6.java | 6 +++--- .../javax/lang/model/util/AbstractElementVisitor7.java | 2 +- .../javax/lang/model/util/AbstractTypeVisitor6.java | 6 +++--- .../javax/lang/model/util/AbstractTypeVisitor7.java | 2 +- .../javax/lang/model/util/ElementKindVisitor6.java | 9 ++++++--- .../javax/lang/model/util/ElementKindVisitor7.java | 3 ++- .../classes/javax/lang/model/util/ElementScanner6.java | 9 ++++++--- .../classes/javax/lang/model/util/ElementScanner7.java | 3 ++- .../lang/model/util/SimpleAnnotationValueVisitor6.java | 9 ++++++--- .../lang/model/util/SimpleAnnotationValueVisitor7.java | 3 ++- .../javax/lang/model/util/SimpleElementVisitor6.java | 9 ++++++--- .../javax/lang/model/util/SimpleElementVisitor7.java | 3 ++- .../javax/lang/model/util/SimpleTypeVisitor6.java | 9 ++++++--- .../javax/lang/model/util/SimpleTypeVisitor7.java | 3 ++- .../classes/javax/lang/model/util/TypeKindVisitor6.java | 9 ++++++--- .../classes/javax/lang/model/util/TypeKindVisitor7.java | 3 ++- 18 files changed, 60 insertions(+), 36 deletions(-) diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java index 8367c1aa587..46cc2707f3e 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java @@ -65,17 +65,17 @@ import javax.annotation.processing.SupportedSourceVersion; * @see AbstractAnnotationValueVisitor8 * @see AbstractAnnotationValueVisitor9 * @since 1.6 - * @deprecated Release 6 is obsolete; update to a visitor for a newer - * release level. */ -@Deprecated @SupportedSourceVersion(RELEASE_6) public abstract class AbstractAnnotationValueVisitor6 implements AnnotationValueVisitor { /** * Constructor for concrete subclasses to call. + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected AbstractAnnotationValueVisitor6() {} /** diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java index 20a77e985d1..ae58cedd6a1 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java @@ -59,13 +59,13 @@ import javax.annotation.processing.SupportedSourceVersion; * @see AbstractAnnotationValueVisitor9 * @since 1.7 */ -@SuppressWarnings("deprecation") // Superclass deprecated @SupportedSourceVersion(RELEASE_7) public abstract class AbstractAnnotationValueVisitor7 extends AbstractAnnotationValueVisitor6 { /** * Constructor for concrete subclasses to call. */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected AbstractAnnotationValueVisitor7() { super(); } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java index daa0e097efd..11e26f1ed5b 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java @@ -67,15 +67,15 @@ import static javax.lang.model.SourceVersion.*; * @see AbstractElementVisitor8 * @see AbstractElementVisitor9 * @since 1.6 - * @deprecated Release 6 is obsolete; update to a visitor for a newer - * release level. */ -@Deprecated @SupportedSourceVersion(RELEASE_6) public abstract class AbstractElementVisitor6 implements ElementVisitor { /** * Constructor for concrete subclasses to call. + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected AbstractElementVisitor6(){} /** diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor7.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor7.java index 69263575588..e53d540e146 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor7.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor7.java @@ -63,12 +63,12 @@ import static javax.lang.model.SourceVersion.*; * @see AbstractElementVisitor9 * @since 1.7 */ -@SuppressWarnings("deprecation") // Superclass deprecated @SupportedSourceVersion(RELEASE_7) public abstract class AbstractElementVisitor7 extends AbstractElementVisitor6 { /** * Constructor for concrete subclasses to call. */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected AbstractElementVisitor7(){ super(); } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java index 8ad1fe1f5db..99fead88ac2 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java @@ -66,15 +66,15 @@ import static javax.lang.model.SourceVersion.*; * @see AbstractTypeVisitor8 * @see AbstractTypeVisitor9 * @since 1.6 - * @deprecated Release 6 is obsolete; update to a visitor for a newer - * release level. */ -@Deprecated @SupportedSourceVersion(RELEASE_6) public abstract class AbstractTypeVisitor6 implements TypeVisitor { /** * Constructor for concrete subclasses to call. + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected AbstractTypeVisitor6() {} /** diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java index 55ac050fb3e..a1edf745258 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java @@ -63,12 +63,12 @@ import static javax.lang.model.SourceVersion.*; * @see AbstractTypeVisitor9 * @since 1.7 */ -@SuppressWarnings("deprecation") // Superclass deprecated @SupportedSourceVersion(RELEASE_7) public abstract class AbstractTypeVisitor7 extends AbstractTypeVisitor6 { /** * Constructor for concrete subclasses to call. */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected AbstractTypeVisitor7() { super(); } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java index 562e6e5cfd2..4913665bfa7 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java @@ -81,17 +81,17 @@ import javax.lang.model.SourceVersion; * @see ElementKindVisitor8 * @see ElementKindVisitor9 * @since 1.6 - * @deprecated Release 6 is obsolete; update to a visitor for a newer - * release level. */ -@Deprecated @SupportedSourceVersion(RELEASE_6) public class ElementKindVisitor6 extends SimpleElementVisitor6 { /** * Constructor for concrete subclasses; uses {@code null} for the * default value. + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected ElementKindVisitor6() { super(null); } @@ -101,7 +101,10 @@ public class ElementKindVisitor6 * default value. * * @param defaultValue the value to assign to {@link #DEFAULT_VALUE} + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected ElementKindVisitor6(R defaultValue) { super(defaultValue); } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor7.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor7.java index 3bf25d10f70..ce3590f2e26 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor7.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor7.java @@ -76,13 +76,13 @@ import static javax.lang.model.SourceVersion.*; * @see ElementKindVisitor9 * @since 1.7 */ -@SuppressWarnings("deprecation") // Superclass deprecated @SupportedSourceVersion(RELEASE_7) public class ElementKindVisitor7 extends ElementKindVisitor6 { /** * Constructor for concrete subclasses; uses {@code null} for the * default value. */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected ElementKindVisitor7() { super(null); } @@ -93,6 +93,7 @@ public class ElementKindVisitor7 extends ElementKindVisitor6 { * * @param defaultValue the value to assign to {@link #DEFAULT_VALUE} */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected ElementKindVisitor7(R defaultValue) { super(defaultValue); } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java index 749cc600d86..7140f8bd59d 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java @@ -92,10 +92,7 @@ import static javax.lang.model.SourceVersion.*; * @see ElementScanner8 * @see ElementScanner9 * @since 1.6 - * @deprecated Release 6 is obsolete; update to a visitor for a newer - * release level. */ -@Deprecated @SupportedSourceVersion(RELEASE_6) public class ElementScanner6 extends AbstractElementVisitor6 { /** @@ -106,7 +103,10 @@ public class ElementScanner6 extends AbstractElementVisitor6 { /** * Constructor for concrete subclasses; uses {@code null} for the * default value. + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected ElementScanner6(){ DEFAULT_VALUE = null; } @@ -116,7 +116,10 @@ public class ElementScanner6 extends AbstractElementVisitor6 { * default value. * * @param defaultValue the default value + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected ElementScanner6(R defaultValue){ DEFAULT_VALUE = defaultValue; } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java index 35b90dcfca6..287f97f091c 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java @@ -89,13 +89,13 @@ import static javax.lang.model.SourceVersion.*; * @see ElementScanner9 * @since 1.7 */ -@SuppressWarnings("deprecation") // Superclass deprecated @SupportedSourceVersion(RELEASE_7) public class ElementScanner7 extends ElementScanner6 { /** * Constructor for concrete subclasses; uses {@code null} for the * default value. */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected ElementScanner7(){ super(null); } @@ -106,6 +106,7 @@ public class ElementScanner7 extends ElementScanner6 { * * @param defaultValue the default value */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected ElementScanner7(R defaultValue){ super(defaultValue); } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java index a979ff5abba..9d33023db95 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java @@ -74,10 +74,7 @@ import javax.annotation.processing.SupportedSourceVersion; * @see SimpleAnnotationValueVisitor8 * @see SimpleAnnotationValueVisitor9 * @since 1.6 - * @deprecated Release 6 is obsolete; update to a visitor for a newer - * release level. */ -@Deprecated @SupportedSourceVersion(RELEASE_6) public class SimpleAnnotationValueVisitor6 extends AbstractAnnotationValueVisitor6 { @@ -92,7 +89,10 @@ public class SimpleAnnotationValueVisitor6 /** * Constructor for concrete subclasses; uses {@code null} for the * default value. + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected SimpleAnnotationValueVisitor6() { super(); DEFAULT_VALUE = null; @@ -103,7 +103,10 @@ public class SimpleAnnotationValueVisitor6 * default value. * * @param defaultValue the value to assign to {@link #DEFAULT_VALUE} + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected SimpleAnnotationValueVisitor6(R defaultValue) { super(); DEFAULT_VALUE = defaultValue; diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java index bb895bc7ac4..2baae42c56c 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java @@ -66,13 +66,13 @@ import static javax.lang.model.SourceVersion.*; * @see SimpleAnnotationValueVisitor9 * @since 1.7 */ -@SuppressWarnings("deprecation") // Superclass deprecated @SupportedSourceVersion(RELEASE_7) public class SimpleAnnotationValueVisitor7 extends SimpleAnnotationValueVisitor6 { /** * Constructor for concrete subclasses; uses {@code null} for the * default value. */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected SimpleAnnotationValueVisitor7() { super(null); } @@ -83,6 +83,7 @@ public class SimpleAnnotationValueVisitor7 extends SimpleAnnotationValueVi * * @param defaultValue the value to assign to {@link #DEFAULT_VALUE} */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected SimpleAnnotationValueVisitor7(R defaultValue) { super(defaultValue); } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java index 81fc96e0aae..8d20148b211 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java @@ -78,10 +78,7 @@ import static javax.lang.model.SourceVersion.*; * @see SimpleElementVisitor8 * @see SimpleElementVisitor9 * @since 1.6 - * @deprecated Release 6 is obsolete; update to a visitor for a newer - * release level. */ -@Deprecated @SupportedSourceVersion(RELEASE_6) public class SimpleElementVisitor6 extends AbstractElementVisitor6 { /** @@ -94,7 +91,10 @@ public class SimpleElementVisitor6 extends AbstractElementVisitor6 { /** * Constructor for concrete subclasses; uses {@code null} for the * default value. + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected SimpleElementVisitor6(){ DEFAULT_VALUE = null; } @@ -104,7 +104,10 @@ public class SimpleElementVisitor6 extends AbstractElementVisitor6 { * default value. * * @param defaultValue the value to assign to {@link #DEFAULT_VALUE} + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected SimpleElementVisitor6(R defaultValue){ DEFAULT_VALUE = defaultValue; } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor7.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor7.java index bbbd77bdb28..009f7851c46 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor7.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor7.java @@ -72,13 +72,13 @@ import static javax.lang.model.SourceVersion.*; * @see SimpleElementVisitor9 * @since 1.7 */ -@SuppressWarnings("deprecation") // Superclass deprecated @SupportedSourceVersion(RELEASE_7) public class SimpleElementVisitor7 extends SimpleElementVisitor6 { /** * Constructor for concrete subclasses; uses {@code null} for the * default value. */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected SimpleElementVisitor7(){ super(null); } @@ -89,6 +89,7 @@ public class SimpleElementVisitor7 extends SimpleElementVisitor6 { * * @param defaultValue the value to assign to {@link #DEFAULT_VALUE} */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected SimpleElementVisitor7(R defaultValue){ super(defaultValue); } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java index eba95187075..b29062d5c8c 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java @@ -78,10 +78,7 @@ import static javax.lang.model.SourceVersion.*; * @see SimpleTypeVisitor8 * @see SimpleTypeVisitor9 * @since 1.6 - * @deprecated Release 6 is obsolete; update to a visitor for a newer - * release level. */ -@Deprecated @SupportedSourceVersion(RELEASE_6) public class SimpleTypeVisitor6 extends AbstractTypeVisitor6 { /** @@ -94,7 +91,10 @@ public class SimpleTypeVisitor6 extends AbstractTypeVisitor6 { /** * Constructor for concrete subclasses; uses {@code null} for the * default value. + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected SimpleTypeVisitor6(){ DEFAULT_VALUE = null; } @@ -104,7 +104,10 @@ public class SimpleTypeVisitor6 extends AbstractTypeVisitor6 { * default value. * * @param defaultValue the value to assign to {@link #DEFAULT_VALUE} + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected SimpleTypeVisitor6(R defaultValue){ DEFAULT_VALUE = defaultValue; } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java index 8a2e05f479c..b857194261f 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java @@ -72,13 +72,13 @@ import static javax.lang.model.SourceVersion.*; * @see SimpleTypeVisitor9 * @since 1.7 */ -@SuppressWarnings("deprecation") // Superclass deprecated @SupportedSourceVersion(RELEASE_7) public class SimpleTypeVisitor7 extends SimpleTypeVisitor6 { /** * Constructor for concrete subclasses; uses {@code null} for the * default value. */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected SimpleTypeVisitor7(){ super(null); } @@ -89,6 +89,7 @@ public class SimpleTypeVisitor7 extends SimpleTypeVisitor6 { * * @param defaultValue the value to assign to {@link #DEFAULT_VALUE} */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected SimpleTypeVisitor7(R defaultValue){ super(defaultValue); } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java index 0917063e54e..2270dd0d350 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java @@ -76,16 +76,16 @@ import static javax.lang.model.SourceVersion.*; * @see TypeKindVisitor7 * @see TypeKindVisitor8 * @since 1.6 - * @deprecated Release 6 is obsolete; update to a visitor for a newer - * release level. */ -@Deprecated @SupportedSourceVersion(RELEASE_6) public class TypeKindVisitor6 extends SimpleTypeVisitor6 { /** * Constructor for concrete subclasses to call; uses {@code null} * for the default value. + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected TypeKindVisitor6() { super(null); } @@ -96,7 +96,10 @@ public class TypeKindVisitor6 extends SimpleTypeVisitor6 { * for the default value. * * @param defaultValue the value to assign to {@link #DEFAULT_VALUE} + * @deprecated Release 6 is obsolete; update to a visitor for a newer + * release level. */ + @Deprecated protected TypeKindVisitor6(R defaultValue) { super(defaultValue); } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor7.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor7.java index 22529917d49..792ba9b37ba 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor7.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor7.java @@ -73,13 +73,13 @@ import javax.lang.model.SourceVersion; * @see TypeKindVisitor8 * @since 1.7 */ -@SuppressWarnings("deprecation") // Superclass deprecated @SupportedSourceVersion(RELEASE_7) public class TypeKindVisitor7 extends TypeKindVisitor6 { /** * Constructor for concrete subclasses to call; uses {@code null} * for the default value. */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected TypeKindVisitor7() { super(null); } @@ -90,6 +90,7 @@ public class TypeKindVisitor7 extends TypeKindVisitor6 { * * @param defaultValue the value to assign to {@link #DEFAULT_VALUE} */ + @SuppressWarnings("deprecation") // Superclass constructor deprecated protected TypeKindVisitor7(R defaultValue) { super(defaultValue); } From a0dee349e1160cad43f02f6c52ee426a8d6d3c8c Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 18 Jan 2017 09:35:23 +0000 Subject: [PATCH 03/16] 8171380: Remove all exports from jdk.jlink Reviewed-by: alanb, mchung, sundar --- langtools/test/TEST.ROOT | 4 ++-- .../ParameterNamesAreNotCopiedToAnonymousInitTest.java | 1 + langtools/test/tools/javac/diags/Example.java | 1 + langtools/test/tools/javap/T7004698.java | 1 + langtools/test/tools/jdeps/APIDeps.java | 3 +++ 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/langtools/test/TEST.ROOT b/langtools/test/TEST.ROOT index 43aafaddba5..a4780af47ab 100644 --- a/langtools/test/TEST.ROOT +++ b/langtools/test/TEST.ROOT @@ -14,8 +14,8 @@ keys=intermittent randomness # Group definitions groups=TEST.groups -# Tests using jtreg 4.2 b04 features -requiredVersion=4.2 b04 +# Tests using jtreg 4.2 b05 features +requiredVersion=4.2 b05 # Use new module options useNewOptions=true diff --git a/langtools/test/tools/javac/T8010737/ParameterNamesAreNotCopiedToAnonymousInitTest.java b/langtools/test/tools/javac/T8010737/ParameterNamesAreNotCopiedToAnonymousInitTest.java index 18cb8ebbe4c..bacde6b9166 100644 --- a/langtools/test/tools/javac/T8010737/ParameterNamesAreNotCopiedToAnonymousInitTest.java +++ b/langtools/test/tools/javac/T8010737/ParameterNamesAreNotCopiedToAnonymousInitTest.java @@ -143,6 +143,7 @@ public class ParameterNamesAreNotCopiedToAnonymousInitTest { Arrays.asList(new File(System.getProperty("test.src"), this.getClass().getName() + ".java"))); java.util.List options = Arrays.asList( + "--add-modules", "jdk.jdeps", "--add-exports", "jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", diff --git a/langtools/test/tools/javac/diags/Example.java b/langtools/test/tools/javac/diags/Example.java index 56f765e114e..bf0b9c3f38a 100644 --- a/langtools/test/tools/javac/diags/Example.java +++ b/langtools/test/tools/javac/diags/Example.java @@ -236,6 +236,7 @@ class Example implements Comparable { // source for import statements or a magic comment for (File pf: procFiles) { if (pf.getName().equals("CreateBadClassFile.java")) { + pOpts.add("--add-modules=jdk.jdeps"); pOpts.add("--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED"); } } diff --git a/langtools/test/tools/javap/T7004698.java b/langtools/test/tools/javap/T7004698.java index 2121899092f..9f05c78de64 100644 --- a/langtools/test/tools/javap/T7004698.java +++ b/langtools/test/tools/javap/T7004698.java @@ -42,6 +42,7 @@ public class T7004698 { File srcFile = new File(srcDir, T7004698.class.getSimpleName() + ".java"); File classesDir = new File("."); compile("-Xjcov", + "--add-modules", "jdk.jdeps", "--add-exports", "jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED", "-d", classesDir.getPath(), srcFile.getPath()); diff --git a/langtools/test/tools/jdeps/APIDeps.java b/langtools/test/tools/jdeps/APIDeps.java index 2e50ccf0135..edf4f75b7bc 100644 --- a/langtools/test/tools/jdeps/APIDeps.java +++ b/langtools/test/tools/jdeps/APIDeps.java @@ -60,6 +60,9 @@ public class APIDeps { Path testsrc = Paths.get(System.getProperty("test.src")); List options = new ArrayList<>(); + // jdk.jdeps is a service provider module so needs to be explicitly included + options.add("--add-modules=jdk.jdeps"); + // add --add-exports String testModules = System.getProperty("test.modules", ""); List addExports = new ArrayList<>(); From 408d7e99f7a3c2722b6c9c7f9f871e66d85a26cc Mon Sep 17 00:00:00 2001 From: Andrey Nazarov Date: Wed, 18 Jan 2017 21:09:19 +0300 Subject: [PATCH 04/16] 8170250: update/improve testing of classfile module attribute Reviewed-by: jjg, jlahoda --- .../attributes/Module/ModuleTest.java | 135 ++++++++++-- .../attributes/Module/ModuleTestBase.java | 206 +++++++++++++++--- .../classfiles/attributes/lib/TestResult.java | 5 +- 3 files changed, 290 insertions(+), 56 deletions(-) diff --git a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java index 059a8213cf7..b19573fbc56 100644 --- a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java +++ b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -24,7 +24,7 @@ /* * @test * @summary Module attribute tests - * @bug 8080878 8161906 8162713 + * @bug 8080878 8161906 8162713 8170250 * @modules java.compiler * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -52,6 +52,28 @@ public class ModuleTest extends ModuleTestBase { testModuleAttribute(base, moduleDescriptor); } + @Test + public void testOpenEmptyModule(Path base) throws Exception { + ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m", ModuleFlag.OPEN) + .write(base); + compile(base); + testModuleAttribute(base, moduleDescriptor); + } + + @Test + public void testModuleName(Path base) throws Exception { + testName("module.name", base.resolve("dot")); + testName("module.exports.component.subcomponent.more.dots", base.resolve("dots")); + testName("moduleName", base.resolve("noDots")); + } + + private void testName(String name, Path path) throws Exception{ + ModuleDescriptor moduleDescriptor = new ModuleDescriptor(name) + .write(path); + compile(path); + testModuleAttribute(path, moduleDescriptor); + } + @Test public void testExports(Path base) throws Exception { ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m") @@ -91,16 +113,6 @@ public class ModuleTest extends ModuleTestBase { testModuleAttribute(base, moduleDescriptor); } - @Test - public void testQualifiedDynamicExports(Path base) throws Exception { - ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m") - .exportsTo("pack", "jdk.compiler") - .write(base); - tb.writeJavaFiles(base, "package pack; public class A { }"); - compile(base); - testModuleAttribute(base, moduleDescriptor); - } - @Test public void testSeveralQualifiedExports(Path base) throws Exception { ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m") @@ -120,6 +132,47 @@ public class ModuleTest extends ModuleTestBase { testModuleAttribute(base, moduleDescriptor); } + @Test + public void testOpens(Path base) throws Exception { + ModuleDescriptor moduleDescriptor = new ModuleDescriptor("module.name") + .opens("pack") + .write(base); + tb.writeJavaFiles(base, "package pack; public class C extends java.util.ArrayList{ }"); + compile(base); + testModuleAttribute(base, moduleDescriptor); + } + + @Test + public void testQualifiedOpens(Path base) throws Exception { + ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m") + .opensTo("pack", "jdk.compiler") + .write(base); + tb.writeJavaFiles(base, "package pack; public class A { }"); + compile(base); + testModuleAttribute(base, moduleDescriptor); + } + + @Test + public void testSeveralOpens(Path base) throws Exception { + ModuleDescriptor moduleDescriptor = new ModuleDescriptor("module.m1.name") + .opensTo("pack", "jdk.compiler, jdk.jdeps") + .opensTo("pack2", "jdk.jdeps") + .opensTo("pack3", "jdk.compiler") + .opensTo("pack4", "jdk.compiler, jdk.jdeps") + .opensTo("pack5", "jdk.compiler") + .opens("pack6") + .write(base); + tb.writeJavaFiles(base, + "package pack; public class A {}", + "package pack2; public class B {}", + "package pack3; public class C {}", + "package pack4; public class C {}", + "package pack5; public class C {}", + "package pack6; public class C {}"); + compile(base); + testModuleAttribute(base, moduleDescriptor); + } + @Test public void testRequires(Path base) throws Exception { ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m") @@ -182,10 +235,12 @@ public class ModuleTest extends ModuleTestBase { .provides("java.util.Collection", "pack2.D") .provides("java.util.List", "pack2.D") .requires("jdk.compiler") + .provides("javax.tools.FileObject", "pack2.E") .provides("com.sun.tools.javac.Main", "pack2.C") .write(base); tb.writeJavaFiles(base, "package pack2; public class D extends java.util.ArrayList{ }", - "package pack2; public class C extends com.sun.tools.javac.Main{ }"); + "package pack2; public class C extends com.sun.tools.javac.Main{ }", + "package pack2; public class E extends javax.tools.SimpleJavaFileObject{ public E(){ super(null,null); } }"); compile(base); testModuleAttribute(base, moduleDescriptor); } @@ -203,9 +258,10 @@ public class ModuleTest extends ModuleTestBase { public void testSeveralUses(Path base) throws Exception { ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m") .uses("java.util.List") - .uses("java.util.Collection") + .uses("java.util.Collection") // from java.base .requires("jdk.compiler") - .uses("javax.tools.JavaCompiler") + .uses("javax.tools.JavaCompiler") // from java.compiler + .uses("com.sun.tools.javac.Main") // from jdk.compiler .write(base); compile(base); testModuleAttribute(base, moduleDescriptor); @@ -216,9 +272,52 @@ public class ModuleTest extends ModuleTestBase { Path m1 = base.resolve("m1x"); ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1x") .exports("pack1") - .exports("pack3") + .opens("pack3") + .exportsTo("packTo1", "m2x") + .opensTo("packTo1", "m2x") // the same as exportsTo + .opensTo("packTo3", "m3x") + .requires("jdk.compiler") + .requires("m2x", RequiresFlag.TRANSITIVE) + .requires("m3x", RequiresFlag.STATIC) + .requires("m4x", RequiresFlag.TRANSITIVE, RequiresFlag.STATIC) + .provides("java.util.List", "pack1.C", "pack2.D") + .uses("java.util.List") + .uses("java.nio.file.Path") + .requires("jdk.jdeps", RequiresFlag.STATIC, RequiresFlag.TRANSITIVE) + .requires("m5x", RequiresFlag.STATIC) + .requires("m6x", RequiresFlag.TRANSITIVE) + .requires("java.compiler") + .opensTo("packTo4", "java.compiler") + .exportsTo("packTo2", "java.compiler") + .opens("pack2") // same as exports + .opens("pack4") + .exports("pack2") + .write(m1); + tb.writeJavaFiles(m1, "package pack1; public class C extends java.util.ArrayList{ }", + "package pack2; public class D extends java.util.ArrayList{ }", + "package pack3; public class D extends java.util.ArrayList{ }", + "package pack4; public class D extends java.util.ArrayList{ }"); + tb.writeJavaFiles(m1, + "package packTo1; public class T1 {}", + "package packTo2; public class T2 {}", + "package packTo3; public class T3 {}", + "package packTo4; public class T4 {}"); + tb.writeJavaFiles(base.resolve("m2x"), "module m2x { }"); + tb.writeJavaFiles(base.resolve("m3x"), "module m3x { }"); + tb.writeJavaFiles(base.resolve("m4x"), "module m4x { }"); + tb.writeJavaFiles(base.resolve("m5x"), "module m5x { }"); + tb.writeJavaFiles(base.resolve("m6x"), "module m6x { }"); + compile(base, "--module-source-path", base.toString(), + "-d", base.toString()); + testModuleAttribute(m1, moduleDescriptor); + } + + @Test + public void testOpenComplexModule(Path base) throws Exception { + Path m1 = base.resolve("m1x"); + ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1x", ModuleFlag.OPEN) + .exports("pack1") .exportsTo("packTo1", "m2x") - .exportsTo("packTo3", "m3x") .requires("jdk.compiler") .requires("m2x", RequiresFlag.TRANSITIVE) .requires("m3x", RequiresFlag.STATIC) @@ -230,9 +329,7 @@ public class ModuleTest extends ModuleTestBase { .requires("m5x", RequiresFlag.STATIC) .requires("m6x", RequiresFlag.TRANSITIVE) .requires("java.compiler") - .exportsTo("packTo4", "java.compiler") .exportsTo("packTo2", "java.compiler") - .exports("pack4") .exports("pack2") .write(m1); tb.writeJavaFiles(m1, "package pack1; public class C extends java.util.ArrayList{ }", diff --git a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java index 9d2563c4525..6dc43614492 100644 --- a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java +++ b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -25,7 +25,6 @@ import com.sun.tools.classfile.ClassFile; import com.sun.tools.classfile.ConstantPool; import com.sun.tools.classfile.ConstantPoolException; import com.sun.tools.classfile.Module_attribute; -import com.sun.tools.javac.util.Pair; import java.io.IOException; import java.lang.annotation.Retention; @@ -36,11 +35,11 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -74,20 +73,30 @@ public class ModuleTestBase { ClassFile classFile = ClassFile.read(modulePath.resolve("module-info.class")); Module_attribute moduleAttribute = (Module_attribute) classFile.getAttribute("Module"); ConstantPool constantPool = classFile.constant_pool; - + testModuleName(moduleDescriptor, moduleAttribute, constantPool); + testModuleFlags(moduleDescriptor, moduleAttribute); testRequires(moduleDescriptor, moduleAttribute, constantPool); testExports(moduleDescriptor, moduleAttribute, constantPool); + testOpens(moduleDescriptor, moduleAttribute, constantPool); testProvides(moduleDescriptor, moduleAttribute, constantPool); testUses(moduleDescriptor, moduleAttribute, constantPool); } + private void testModuleName(ModuleDescriptor moduleDescriptor, Module_attribute module, ConstantPool constantPool) throws ConstantPoolException { + tr.checkEquals(constantPool.getModuleInfo(module.module_name).getName(), moduleDescriptor.name, "Unexpected module name"); + } + + private void testModuleFlags(ModuleDescriptor moduleDescriptor, Module_attribute module) { + tr.checkEquals(module.module_flags, moduleDescriptor.flags, "Unexpected module flags"); + } + private void testRequires(ModuleDescriptor moduleDescriptor, Module_attribute module, ConstantPool constantPool) throws ConstantPoolException { tr.checkEquals(module.requires_count, moduleDescriptor.requires.size(), "Wrong amount of requires."); - List> actualRequires = new ArrayList<>(); + List actualRequires = new ArrayList<>(); for (Module_attribute.RequiresEntry require : module.requires) { - actualRequires.add(Pair.of( - require.getRequires(constantPool).replace('/', '.'), + actualRequires.add(new Requires( + require.getRequires(constantPool), require.requires_flags)); } tr.checkContains(actualRequires, moduleDescriptor.requires, "Lists of requires don't match"); @@ -104,18 +113,36 @@ public class ModuleTestBase { tr.checkEquals(export.exports_to_count, expectedTo.size(), "Wrong amount of exports to"); List actualTo = new ArrayList<>(); for (int toIdx : export.exports_to_index) { - actualTo.add(constantPool.getModuleInfo(toIdx).getName().replace('/', '.')); + actualTo.add(constantPool.getModuleInfo(toIdx).getName()); } tr.checkContains(actualTo, expectedTo, "Lists of \"exports to\" don't match."); } } } + private void testOpens(ModuleDescriptor moduleDescriptor, Module_attribute module, ConstantPool constantPool) throws ConstantPoolException { + tr.checkEquals(module.opens_count, moduleDescriptor.opens.size(), "Wrong amount of opens."); + for (Module_attribute.OpensEntry open : module.opens) { + String pkg = constantPool.getPackageInfo(open.opens_index).getName(); + if (tr.checkTrue(moduleDescriptor.opens.containsKey(pkg), "Unexpected open " + pkg)) { + Open expectedOpen = moduleDescriptor.opens.get(pkg); + tr.checkEquals(expectedOpen.mask, open.opens_flags, "Wrong open flags"); + List expectedTo = expectedOpen.to; + tr.checkEquals(open.opens_to_count, expectedTo.size(), "Wrong amount of opens to"); + List actualTo = new ArrayList<>(); + for (int toIdx : open.opens_to_index) { + actualTo.add(constantPool.getModuleInfo(toIdx).getName()); + } + tr.checkContains(actualTo, expectedTo, "Lists of \"opens to\" don't match."); + } + } + } + private void testUses(ModuleDescriptor moduleDescriptor, Module_attribute module, ConstantPool constantPool) throws ConstantPoolException { tr.checkEquals(module.uses_count, moduleDescriptor.uses.size(), "Wrong amount of uses."); List actualUses = new ArrayList<>(); for (int usesIdx : module.uses_index) { - String uses = constantPool.getClassInfo(usesIdx).getBaseName().replace('/', '.'); + String uses = constantPool.getClassInfo(usesIdx).getBaseName(); actualUses.add(uses); } tr.checkContains(actualUses, moduleDescriptor.uses, "Lists of uses don't match"); @@ -131,10 +158,10 @@ public class ModuleTestBase { tr.checkEquals(moduleProvidesCount, moduleDescriptorProvidesCount, "Wrong amount of provides."); Map> actualProvides = new HashMap<>(); for (Module_attribute.ProvidesEntry provide : module.provides) { - String provides = constantPool.getClassInfo(provide.provides_index).getBaseName().replace('/', '.'); + String provides = constantPool.getClassInfo(provide.provides_index).getBaseName(); List impls = new ArrayList<>(); for (int i = 0; i < provide.with_count; i++) { - String with = constantPool.getClassInfo(provide.with_index[i]).getBaseName().replace('/', '.'); + String with = constantPool.getClassInfo(provide.with_index[i]).getBaseName(); impls.add(with); } actualProvides.put(provides, impls); @@ -163,9 +190,27 @@ public class ModuleTestBase { int getMask(); } + public enum ModuleFlag implements Mask { + OPEN("open", Module_attribute.ACC_OPEN); + + private final String token; + private final int mask; + + ModuleFlag(String token, int mask) { + this.token = token; + this.mask = mask; + } + + @Override + public int getMask() { + return mask; + } + } + public enum RequiresFlag implements Mask { TRANSITIVE("transitive", Module_attribute.ACC_TRANSITIVE), - STATIC("static", Module_attribute.ACC_STATIC_PHASE); + STATIC("static", Module_attribute.ACC_STATIC_PHASE), + MANDATED("", Module_attribute.ACC_MANDATED); private final String token; private final int mask; @@ -181,13 +226,30 @@ public class ModuleTestBase { } } - public enum ExportFlag implements Mask { + public enum ExportsFlag implements Mask { SYNTHETIC("", Module_attribute.ACC_SYNTHETIC); private final String token; private final int mask; - ExportFlag(String token, int mask) { + ExportsFlag(String token, int mask) { + this.token = token; + this.mask = mask; + } + + @Override + public int getMask() { + return mask; + } + } + + public enum OpensFlag implements Mask { + SYNTHETIC("", Module_attribute.ACC_SYNTHETIC); + + private final String token; + private final int mask; + + OpensFlag(String token, int mask) { this.token = token; this.mask = mask; } @@ -199,27 +261,64 @@ public class ModuleTestBase { } private class Export { - String pkg; - int mask; - List to = new ArrayList<>(); + private final String pkg; + private final int mask; + private final List to = new ArrayList<>(); - public Export(String pkg, int mask) { + Export(String pkg, int mask) { this.pkg = pkg; this.mask = mask; } } + private class Open { + private final String pkg; + private final int mask; + private final List to = new ArrayList<>(); + + Open(String pkg, int mask) { + this.pkg = pkg; + this.mask = mask; + } + } + + private class Requires { + private final String module; + private final int mask; + + Requires(String module, int mask) { + this.module = module; + this.mask = mask; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Requires requires = (Requires) o; + return mask == requires.mask && + Objects.equals(module, requires.module); + } + + @Override + public int hashCode() { + return Objects.hash(module, mask); + } + } + protected class ModuleDescriptor { private final String name; - //pair is name of module and flag(public,mandated,synthetic) - private final List> requires = new ArrayList<>(); + private final int flags; + + private final List requires = new ArrayList<>(); { - requires.add(new Pair<>("java.base", Module_attribute.ACC_MANDATED)); + requires.add(new Requires("java.base", computeMask(RequiresFlag.MANDATED))); } private final Map exports = new HashMap<>(); + private final Map opens = new HashMap<>(); //List of service and implementation private final Map> provides = new LinkedHashMap<>(); @@ -227,22 +326,26 @@ public class ModuleTestBase { private static final String LINE_END = ";\n"; - StringBuilder content = new StringBuilder("module "); + StringBuilder content = new StringBuilder(""); - public ModuleDescriptor(String moduleName) { + public ModuleDescriptor(String moduleName, ModuleFlag... flags) { this.name = moduleName; - content.append(name).append('{').append('\n'); + this.flags = computeMask(flags); + for (ModuleFlag flag : flags) { + content.append(flag.token).append(" "); + } + content.append("module ").append(moduleName).append('{').append('\n'); } public ModuleDescriptor requires(String module) { - this.requires.add(Pair.of(module, 0)); + this.requires.add(new Requires(module, 0)); content.append(" requires ").append(module).append(LINE_END); return this; } public ModuleDescriptor requires(String module, RequiresFlag... flags) { - this.requires.add(new Pair<>(module, computeMask(flags))); + this.requires.add(new Requires(module, computeMask(flags))); content.append(" requires "); for (RequiresFlag flag : flags) { @@ -253,26 +356,52 @@ public class ModuleTestBase { return this; } - public ModuleDescriptor exports(String pkg, ExportFlag... flags) { - this.exports.putIfAbsent(pkg, new Export(pkg, computeMask(flags))); + public ModuleDescriptor exports(String pkg, ExportsFlag... flags) { + this.exports.put(toInternalForm(pkg), new Export(toInternalForm(pkg), computeMask(flags))); content.append(" exports "); - for (ExportFlag flag : flags) { + for (ExportsFlag flag : flags) { content.append(flag.token).append(" "); } content.append(pkg).append(LINE_END); return this; } - public ModuleDescriptor exportsTo(String pkg, String to, ExportFlag... flags) { + public ModuleDescriptor exportsTo(String pkg, String to, ExportsFlag... flags) { List tos = Pattern.compile(",") .splitAsStream(to) .map(String::trim) .collect(Collectors.toList()); - this.exports.computeIfAbsent(pkg, k -> new Export(pkg, computeMask(flags))) + this.exports.compute(toInternalForm(pkg), (k,v) -> new Export(k, computeMask(flags))) .to.addAll(tos); content.append(" exports "); - for (ExportFlag flag : flags) { + for (ExportsFlag flag : flags) { + content.append(flag.token).append(" "); + } + content.append(pkg).append(" to ").append(to).append(LINE_END); + return this; + } + + public ModuleDescriptor opens(String pkg, OpensFlag... flags) { + this.opens.put(toInternalForm(pkg), new Open(toInternalForm(pkg), computeMask(flags))); + content.append(" opens "); + for (OpensFlag flag : flags) { + content.append(flag.token).append(" "); + } + content.append(pkg).append(LINE_END); + return this; + } + + public ModuleDescriptor opensTo(String pkg, String to, OpensFlag... flags) { + List tos = Pattern.compile(",") + .splitAsStream(to) + .map(String::trim) + .collect(Collectors.toList()); + this.opens.compute(toInternalForm(pkg), (k,v) -> new Open(toInternalForm(k), computeMask(flags))) + .to.addAll(tos); + + content.append(" opens "); + for (OpensFlag flag : flags) { content.append(flag.token).append(" "); } content.append(pkg).append(" to ").append(to).append(LINE_END); @@ -280,7 +409,10 @@ public class ModuleTestBase { } public ModuleDescriptor provides(String provides, String... with) { - this.provides.put(provides, Arrays.asList(with)); + List impls = Arrays.stream(with) + .map(this::toInternalForm) + .collect(Collectors.toList()); + this.provides.put(toInternalForm(provides), impls); content.append(" provides ") .append(provides) .append(" with ") @@ -290,8 +422,8 @@ public class ModuleTestBase { } public ModuleDescriptor uses(String... uses) { - Collections.addAll(this.uses, uses); for (String use : uses) { + this.uses.add(toInternalForm(use)); content.append(" uses ").append(use).append(LINE_END); } return this; @@ -305,7 +437,11 @@ public class ModuleTestBase { return this; } - private int computeMask(Mask[] masks) { + private String toInternalForm(String name) { + return name.replace('.', '/'); + } + + private int computeMask(Mask... masks) { return Arrays.stream(masks) .map(Mask::getMask) .reduce((a, b) -> a | b) diff --git a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java index 7160879675e..39b727cecea 100644 --- a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java +++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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 @@ -82,7 +82,8 @@ public class TestResult extends TestBase { Set copy = new HashSet<>(expected); copy.removeAll(found); if (!found.containsAll(expected)) { - return checkTrue(false, message + " FAIL : not found elements : " + copy); + return checkTrue(false, message + " FAIL : not found elements : " + copy + "\n" + + "Actual: " + found); } else { return checkTrue(true, message + " PASS : all elements found"); } From 5fe31c310c01400d6daf584183036fe8efd15324 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 18 Jan 2017 19:39:06 -0800 Subject: [PATCH 05/16] 8172910: Use default methods as appropriate for language model visitors Reviewed-by: jjg --- .../model/element/AnnotationValueVisitor.java | 13 +- .../lang/model/element/ElementVisitor.java | 21 +- .../javax/lang/model/type/TypeVisitor.java | 13 +- .../model/util/AbstractElementVisitor6.java | 3 +- .../processing/model/TestVisitorDefaults.java | 226 ++++++++++++++++++ 5 files changed, 262 insertions(+), 14 deletions(-) create mode 100644 langtools/test/tools/javac/processing/model/TestVisitorDefaults.java diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValueVisitor.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValueVisitor.java index 8e152c53ead..dabf7ed29b5 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValueVisitor.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValueVisitor.java @@ -68,8 +68,8 @@ import javax.lang.model.type.TypeMirror; * javax.lang.model.*} packages bundled in Java SE 8 were required to * also be runnable on Java SE 7. Therefore, default methods * were not used when extending {@code javax.lang.model.*} - * to cover Java SE 8 language features. However, default methods may - * be used in subsequent revisions of the {@code javax.lang.model.*} + * to cover Java SE 8 language features. However, default methods + * are used in subsequent revisions of the {@code javax.lang.model.*} * packages that are only required to run on Java SE 8 and higher * platform versions. * @@ -90,11 +90,16 @@ public interface AnnotationValueVisitor { R visit(AnnotationValue av, P p); /** - * A convenience method equivalent to {@code v.visit(av, null)}. + * A convenience method equivalent to {@code visit(av, null)}. + * + * @implSpec The default implementation is {@code visit(av, null)}. + * * @param av the value to visit * @return a visitor-specified result */ - R visit(AnnotationValue av); + default R visit(AnnotationValue av) { + return visit(av, null); + } /** * Visits a {@code boolean} value in an annotation. diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java index b549fbd3e00..290c36fedda 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java @@ -59,8 +59,8 @@ import javax.lang.model.util.*; * javax.lang.model.*} packages bundled in Java SE 8 were required to * also be runnable on Java SE 7. Therefore, default methods * were not used when extending {@code javax.lang.model.*} - * to cover Java SE 8 language features. However, default methods may - * be used in subsequent revisions of the {@code javax.lang.model.*} + * to cover Java SE 8 language features. However, default methods + * are used in subsequent revisions of the {@code javax.lang.model.*} * packages that are only required to run on Java SE 8 and higher * platform versions. * @@ -85,11 +85,16 @@ public interface ElementVisitor { R visit(Element e, P p); /** - * A convenience method equivalent to {@code v.visit(e, null)}. + * A convenience method equivalent to {@code visit(e, null)}. + * + * @implSpec The default implementation is {@code visit(e, null)}. + * * @param e the element to visit * @return a visitor-specified result */ - R visit(Element e); + default R visit(Element e) { + return visit(e, null); + } /** * Visits a package element. @@ -146,10 +151,16 @@ public interface ElementVisitor { /** * Visits a module element. + * + * @implSpec Visits a {@code ModuleElement} by calling {@code + * visitUnknown(e, p)}. + * * @param e the element to visit * @param p a visitor-specified parameter * @return a visitor-specified result * @since 9 */ - R visitModule(ModuleElement e, P p); + default R visitModule(ModuleElement e, P p) { + return visitUnknown(e, p); + } } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeVisitor.java b/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeVisitor.java index 451753a0095..a5d19a02d89 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeVisitor.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeVisitor.java @@ -59,8 +59,8 @@ import javax.lang.model.element.*; * javax.lang.model.*} packages bundled in Java SE 8 were required to * also be runnable on Java SE 7. Therefore, default methods * were not used when extending {@code javax.lang.model.*} - * to cover Java SE 8 language features. However, default methods may - * be used in subsequent revisions of the {@code javax.lang.model.*} + * to cover Java SE 8 language features. However, default methods + * are used in subsequent revisions of the {@code javax.lang.model.*} * packages that are only required to run on Java SE 8 and higher * platform versions. * @@ -85,11 +85,16 @@ public interface TypeVisitor { R visit(TypeMirror t, P p); /** - * A convenience method equivalent to {@code v.visit(t, null)}. + * A convenience method equivalent to {@code visit(t, null)}. + * + * @implSpec The default implementation is {@code visit(t, null)}. + * * @param t the element to visit * @return a visitor-specified result */ - R visit(TypeMirror t); + default R visit(TypeMirror t) { + return visit(t, null); + } /** * Visits a primitive type. diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java index 11e26f1ed5b..0db2e75549f 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java @@ -139,6 +139,7 @@ public abstract class AbstractElementVisitor6 implements ElementVisitor { + + public DirectElementVisitorChild() { + super(); + } + + @Override + public String visitModule(ModuleElement e, Object o) { + return ElementVisitor.super.visitModule(e, null); + } + + @Override + public String visitUnknown(Element e, Object o) { + return "visitUnknown"; + } + + @Override + public String visit(Element e) { + return ElementVisitor.super.visit(e); + } + + @Override + public String visit(Element e, Object o) { + return "visit"; + } + + @Override + public String visitExecutable(ExecutableElement e, Object o) { return throwUOE(); } + @Override + public String visitPackage(PackageElement e, Object o) { return throwUOE(); } + @Override + public String visitType(TypeElement e, Object o) { return throwUOE(); } + @Override + public String visitTypeParameter(TypeParameterElement e, Object o) { return throwUOE(); } + @Override + public String visitVariable(VariableElement e, Object o) { return throwUOE(); } + } + + private static class IndirectElementVisitorChild + extends AbstractElementVisitor6 { + + public IndirectElementVisitorChild() { + super(); + } + + @Override + public String visitModule(ModuleElement e, Object o) { + return super.visitModule(e, o); + } + + + @Override + public String visitUnknown(Element e, Object o) { + return "visitUnknown"; + } + + @Override + public String visitExecutable(ExecutableElement e, Object o) { return throwUOE(); } + @Override + public String visitPackage(PackageElement e, Object o) { return throwUOE(); } + @Override + public String visitType(TypeElement e, Object o) { return throwUOE(); } + @Override + public String visitTypeParameter(TypeParameterElement e, Object o) { return throwUOE(); } + @Override + public String visitVariable(VariableElement e, Object o) { return throwUOE(); } + } + + + private static class DirectTypeVisitorChild + implements TypeVisitor { + + public DirectTypeVisitorChild() { + super(); + } + + @Override + public String visit(TypeMirror t) { + return TypeVisitor.super.visit(t); + } + + @Override + public String visit(TypeMirror t, Object o) { + return "visit"; + } + + @Override + public String visitUnknown(TypeMirror t, Object o) { return throwUOE(); } + @Override + public String visitArray(ArrayType t, Object o) { return throwUOE(); } + @Override + public String visitDeclared(DeclaredType t, Object o) { return throwUOE(); } + @Override + public String visitError(ErrorType t, Object o) { return throwUOE(); } + @Override + public String visitExecutable(ExecutableType t, Object o) { return throwUOE(); } + @Override + public String visitIntersection(IntersectionType t, Object o) { return throwUOE(); } + @Override + public String visitNoType(NoType t, Object o) { return throwUOE(); } + @Override + public String visitNull(NullType t, Object o) { return throwUOE(); } + @Override + public String visitPrimitive(PrimitiveType t, Object o) { return throwUOE(); } + @Override + public String visitTypeVariable(TypeVariable t, Object o) { return throwUOE(); } + @Override + public String visitUnion(UnionType t, Object o) { return throwUOE(); } + @Override + public String visitWildcard(WildcardType t, Object o) { return throwUOE(); } + } + + private static class DirectAnnotationVisitorChild + implements AnnotationValueVisitor { + + @Override + public String visit(AnnotationValue av) { + return AnnotationValueVisitor.super.visit(av); + } + + @Override + public String visit(AnnotationValue av, Object o) { + return "visit"; + } + + @Override + public String visitAnnotation(AnnotationMirror a, Object o) { return throwUOE(); } + @Override + public String visitArray(List vals, + Object o) { return throwUOE(); } + @Override + public String visitBoolean(boolean b, Object o) { return throwUOE(); } + @Override + public String visitByte(byte b, Object o) { return throwUOE(); } + @Override + public String visitChar(char c, Object o) { return throwUOE(); } + @Override + public String visitDouble(double d, Object o) { return throwUOE(); } + @Override + public String visitEnumConstant(VariableElement c, Object o) { return throwUOE(); } + @Override + public String visitFloat(float f, Object o) { return throwUOE(); } + @Override + public String visitInt(int i, Object o) { return throwUOE(); } + @Override + public String visitLong(long i, Object o) { return throwUOE(); } + @Override + public String visitShort(short s, Object o) { return throwUOE(); } + @Override + public String visitString(String s, Object o) { return throwUOE(); } + @Override + public String visitType(TypeMirror t, Object o) { return throwUOE(); } + @Override + public String visitUnknown(AnnotationValue av, Object o) { return throwUOE(); } + } + + private static String throwUOE() { + throw new UnsupportedOperationException(); + } +} From 99e3bceb60b75e00f70d1a1cc7cbf17ad7b4f61e Mon Sep 17 00:00:00 2001 From: Robert Field Date: Thu, 19 Jan 2017 11:12:02 -0800 Subject: [PATCH 06/16] 8172179: jshell tool: builtin startup settings should be by reference not content Reviewed-by: jlahoda --- .../jdk/internal/jshell/tool/JShellTool.java | 147 +++----- .../jdk/internal/jshell/tool/Startup.java | 352 ++++++++++++++++++ .../jshell/tool/resources/l10n.properties | 2 + .../jdk/jshell/tool/resources/DEFAULT.jsh | 1 - .../jdk/jshell/ToolCommandOptionTest.java | 30 +- 5 files changed, 417 insertions(+), 115 deletions(-) create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 4d80149d421..94dcf3a52bf 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -128,9 +128,8 @@ import static jdk.internal.jshell.tool.ContinuousCompletionProvider.STARTSWITH_M */ public class JShellTool implements MessageHandler { - private static final String LINE_SEP = System.getProperty("line.separator"); private static final Pattern LINEBREAK = Pattern.compile("\\R"); - private static final String RECORD_SEPARATOR = "\u241E"; + static final String RECORD_SEPARATOR = "\u241E"; private static final String RB_NAME_PREFIX = "jdk.internal.jshell.tool.resources"; private static final String VERSION_RB_NAME = RB_NAME_PREFIX + ".version"; private static final String L10N_RB_NAME = RB_NAME_PREFIX + ".l10n"; @@ -199,7 +198,7 @@ public class JShellTool implements MessageHandler { private boolean debug = false; public boolean testPrompt = false; private String defaultStartup = null; - private String startup = null; + private Startup startup = null; private String executionControlSpec = null; private EditorSetting editor = BUILT_IN_EDITOR; @@ -216,7 +215,6 @@ public class JShellTool implements MessageHandler { static final String MODE_KEY = "MODE"; static final String REPLAY_RESTORE_KEY = "REPLAY_RESTORE"; - static final String DEFAULT_STARTUP_NAME = "DEFAULT"; static final Pattern BUILTIN_FILE_PATTERN = Pattern.compile("\\w+"); static final String BUILTIN_FILE_PATH_FORMAT = "/jdk/jshell/tool/resources/%s.jsh"; @@ -431,13 +429,13 @@ public class JShellTool implements MessageHandler { private final OptionSpecBuilder argX = parser.accepts("X"); private String feedbackMode = null; - private String initialStartup = null; + private Startup initialStartup = null; String feedbackMode() { return feedbackMode; } - String startup() { + Startup startup() { return initialStartup; } @@ -485,22 +483,15 @@ public class JShellTool implements MessageHandler { startmsg("jshell.err.opt.startup.conflict"); return null; } - StringBuilder sb = new StringBuilder(); - for (String fn : sts) { - String s = readFile(fn, "--startup"); - if (s == null) { - return null; - } - sb.append(s); - } - initialStartup = sb.toString(); - } else if (options.has(argNoStart)) { - initialStartup = ""; - } else { - initialStartup = prefs.get(STARTUP_KEY); + initialStartup = Startup.fromFileList(sts, "--startup", new InitMessageHandler()); if (initialStartup == null) { - initialStartup = defaultStartup(); + return null; } + } else if (options.has(argNoStart)) { + initialStartup = Startup.noStartup(); + } else { + String packedStartup = prefs.get(STARTUP_KEY); + initialStartup = Startup.unpack(packedStartup, new InitMessageHandler()); } if (options.has(argExecution)) { executionControlSpec = options.valueOf(argExecution); @@ -639,6 +630,11 @@ public class JShellTool implements MessageHandler { return ""; } String pp = s.replaceAll("\\R", post + pre); + if (pp.endsWith(post + pre)) { + // prevent an extra prefix char and blank line when the string + // already terminates with newline + pp = pp.substring(0, pp.length() - (post + pre).length()); + } return pre + pp + post; } @@ -893,7 +889,7 @@ public class JShellTool implements MessageHandler { analysis = state.sourceCodeAnalysis(); live = true; - startUpRun(startup); + startUpRun(startup.toString()); currentNameSpace = mainNamespace; } @@ -1077,7 +1073,7 @@ public class JShellTool implements MessageHandler { .toArray(Command[]::new); } - private static Path toPathResolvingUserHome(String pathString) { + static Path toPathResolvingUserHome(String pathString) { if (pathString.replace(File.separatorChar, '/').startsWith("~/")) return Paths.get(System.getProperty("user.home"), pathString.substring(2)); else @@ -1838,48 +1834,43 @@ public class JShellTool implements MessageHandler { return true; } if (hasFile) { - StringBuilder sb = new StringBuilder(); - for (String fn : fns) { - String s = readFile(fn, "/set start"); - if (s == null) { - return false; - } - sb.append(s); + startup = Startup.fromFileList(fns, "/set start", this); + if (startup == null) { + return false; } - startup = sb.toString(); } else if (defaultOption) { - startup = defaultStartup(); + startup = Startup.defaultStartup(this); } else if (noneOption) { - startup = ""; + startup = Startup.noStartup(); } if (retainOption) { // retain startup setting - prefs.put(STARTUP_KEY, startup); + prefs.put(STARTUP_KEY, startup.storedForm()); } return true; } + // show the "/set start" settings (retained and, if different, current) + // as commands (and file contents). All commands first, then contents. void showSetStart() { + StringBuilder sb = new StringBuilder(); String retained = prefs.get(STARTUP_KEY); if (retained != null) { - showSetStart(true, retained); - } - if (retained == null || !startup.equals(retained)) { - showSetStart(false, startup); - } - } - - void showSetStart(boolean isRetained, String start) { - String cmd = "/set start" + (isRetained ? " -retain " : " "); - String stset; - if (start.equals(defaultStartup())) { - stset = cmd + "-default"; - } else if (start.isEmpty()) { - stset = cmd + "-none"; + Startup retainedStart = Startup.unpack(retained, this); + boolean currentDifferent = !startup.equals(retainedStart); + sb.append(retainedStart.show(true)); + if (currentDifferent) { + sb.append(startup.show(false)); + } + sb.append(retainedStart.showDetail()); + if (currentDifferent) { + sb.append(startup.showDetail()); + } } else { - stset = "startup.jsh:\n" + start + "\n" + cmd + "startup.jsh"; + sb.append(startup.show(false)); + sb.append(startup.showDetail()); } - hard(stset); + hard(sb.toString()); } boolean cmdDebug(String arg) { @@ -2380,38 +2371,7 @@ public class JShellTool implements MessageHandler { return false; } - /** - * Read an external file. Error messages accessed via keyPrefix - * - * @param filename file to access or null - * @param context printable non-natural language context for errors - * @return contents of file as string - */ - String readFile(String filename, String context) { - if (filename != null) { - try { - byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename)); - return new String(encoded); - } catch (AccessDeniedException e) { - errormsg("jshell.err.file.not.accessible", context, filename, e.getMessage()); - } catch (NoSuchFileException e) { - String resource = getResource(filename); - if (resource != null) { - // Not found as file, but found as resource - return resource; - } - errormsg("jshell.err.file.not.found", context, filename); - } catch (Exception e) { - errormsg("jshell.err.file.exception", context, filename, e); - } - } else { - errormsg("jshell.err.file.filename", context); - } - return null; - - } - - String getResource(String name) { + static String getResource(String name) { if (BUILTIN_FILE_PATTERN.matcher(name).matches()) { try { return readResource(name); @@ -2423,33 +2383,16 @@ public class JShellTool implements MessageHandler { } // Read a built-in file from resources - String readResource(String name) throws IOException { + static String readResource(String name) throws IOException { // Attempt to find the file as a resource String spec = String.format(BUILTIN_FILE_PATH_FORMAT, name); try (InputStream in = JShellTool.class.getResourceAsStream(spec); - BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { - return reader.lines().collect(Collectors.joining("\n")); + BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { + return reader.lines().collect(Collectors.joining("\n", "", "\n")); } } - // retrieve the default startup string - String defaultStartup() { - if (defaultStartup == null) { - defaultStartup = ""; // failure case - try { - defaultStartup = readResource(DEFAULT_STARTUP_NAME); - } catch (AccessDeniedException e) { - errormsg("jshell.err.file.not.accessible", "jshell", DEFAULT_STARTUP_NAME, e.getMessage()); - } catch (NoSuchFileException e) { - errormsg("jshell.err.file.not.found", "jshell", DEFAULT_STARTUP_NAME); - } catch (Exception e) { - errormsg("jshell.err.file.exception", "jshell", DEFAULT_STARTUP_NAME, e); - } - } - return defaultStartup; - } - private boolean cmdReset(String rawargs) { if (!parseCommandLineLikeFlags(rawargs, new OptionParserBase())) { return false; @@ -2551,7 +2494,7 @@ public class JShellTool implements MessageHandler { writer.write("\n"); } } else if (at.hasOption("-start")) { - writer.append(startup); + writer.append(startup.toString()); } else { String sources = (at.hasOption("-all") ? state.snippets() diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java new file mode 100644 index 00000000000..da8b342e4f7 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2016, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.internal.jshell.tool; + +import java.nio.file.AccessDeniedException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toList; +import static jdk.internal.jshell.tool.JShellTool.RECORD_SEPARATOR; +import static jdk.internal.jshell.tool.JShellTool.getResource; +import static jdk.internal.jshell.tool.JShellTool.readResource; +import static jdk.internal.jshell.tool.JShellTool.toPathResolvingUserHome; + +/** + * Processing start-up "script" information. The startup may consist of several + * entries, each of which may have been read from a user file or be a built-in + * resource. The startup may also be empty ("-none"); Which is stored as the + * empty string different from unset (null). Built-in resources come from + * resource files. Startup is stored as named elements rather than concatenated + * text, for display purposes but also importantly so that when resources update + * with new releases the built-in will update. + * @author Robert Field + */ +class Startup { + + // Store one entry in the start-up list + private static class StartupEntry { + + // is this a JShell built-in? + private final boolean isBuiltIn; + + // the file or resource name + private final String name; + + // the commands/snippets as text + private final String content; + + // for files, the date/time read in -- makes clear it is a snapshot + private final String timeStamp; + + StartupEntry(boolean isBuiltIn, String name, String content) { + this(isBuiltIn, name, content, ""); + } + + StartupEntry(boolean isBuiltIn, String name, String content, String timeStamp) { + this.isBuiltIn = isBuiltIn; + this.name = name; + this.content = content; + this.timeStamp = timeStamp; + } + + // string form to store in storage (e.g. Preferences) + String storedForm() { + return (isBuiltIn ? "*" : "-") + RECORD_SEPARATOR + + name + RECORD_SEPARATOR + + timeStamp + RECORD_SEPARATOR + + content + RECORD_SEPARATOR; + } + + // the content + @Override + public String toString() { + return content; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 41 * hash + (this.isBuiltIn ? 1 : 0); + hash = 41 * hash + Objects.hashCode(this.name); + if (!isBuiltIn) { + hash = 41 * hash + Objects.hashCode(this.content); + } + return hash; + } + + // built-ins match on name only. Time stamp isn't considered + @Override + public boolean equals(Object o) { + if (!(o instanceof StartupEntry)) { + return false; + } + StartupEntry sue = (StartupEntry) o; + return isBuiltIn == sue.isBuiltIn && + name.equals(sue.name) && + (isBuiltIn || content.equals(sue.content)); + } + } + + private static final String DEFAULT_STARTUP_NAME = "DEFAULT"; + + // cached DEFAULT start-up + private static Startup defaultStartup = null; + + // the list of entries + private List entries; + + // the concatenated content of the list of entries + private String content; + + // created only with factory methods (below) + private Startup(List entries) { + this.entries = entries; + this.content = entries.stream() + .map(sue -> sue.toString()) + .collect(joining()); + } + + private Startup(StartupEntry entry) { + this(Collections.singletonList(entry)); + } + + // retrieve the content + @Override + public String toString() { + return content; + } + + @Override + public int hashCode() { + return 9 + Objects.hashCode(this.entries); + } + + @Override + public boolean equals(Object o) { + return (o instanceof Startup) + && entries.equals(((Startup) o).entries); + } + + // are there no entries ("-none")? + boolean isEmpty() { + return entries.isEmpty(); + } + + // is this the "-default" setting -- one entry which is DEFAULT + boolean isDefault() { + if (entries.size() == 1) { + StartupEntry sue = entries.get(0); + if (sue.isBuiltIn && sue.name.equals(DEFAULT_STARTUP_NAME)) { + return true; + } + } + return false; + } + + // string form to store in storage (e.g. Preferences) + String storedForm() { + return entries.stream() + .map(sue -> sue.storedForm()) + .collect(joining()); + } + + // show commands to re-create + String show(boolean isRetained) { + String cmd = "/set start " + (isRetained ? "-retain " : ""); + if (isDefault()) { + return cmd + "-default\n"; + } else if (isEmpty()) { + return cmd + "-none\n"; + } else { + return entries.stream() + .map(sue -> sue.name) + .collect(joining(" ", cmd, "\n")); + } + } + + // show corresponding contents for show() + String showDetail() { + if (isDefault() || isEmpty()) { + return ""; + } else { + return entries.stream() + .map(sue -> "---- " + sue.name + + (sue.timeStamp.isEmpty() + ? "" + : " @ " + sue.timeStamp) + + " ----\n" + sue.content) + .collect(joining()); + } + } + + /** + * Factory method: Unpack from stored form. + * + * @param storedForm the Startup in the form as stored on persistent + * storage (e.g. Preferences) + * @param mh handler for error messages + * @return Startup, or default startup when error (message has been printed) + */ + static Startup unpack(String storedForm, MessageHandler mh) { + if (storedForm != null) { + if (storedForm.isEmpty()) { + return noStartup(); + } + try { + String[] all = storedForm.split(RECORD_SEPARATOR); + if (all.length == 1) { + // legacy (content only) + return new Startup(new StartupEntry(false, "user.jsh", storedForm)); + } else if (all.length % 4 == 0) { + List e = new ArrayList<>(all.length / 4); + for (int i = 0; i < all.length; i += 4) { + final boolean isBuiltIn; + switch (all[i]) { + case "*": + isBuiltIn = true; + break; + case "-": + isBuiltIn = false; + break; + default: + throw new IllegalArgumentException("Unexpected StartupEntry kind: " + all[i]); + } + String name = all[i + 1]; + String timeStamp = all[i + 2]; + String content = all[i + 3]; + if (isBuiltIn) { + // update to current definition, use stored if removed/error + String resource = getResource(name); + if (resource != null) { + content = resource; + } + } + e.add(new StartupEntry(isBuiltIn, name, content, timeStamp)); + } + return new Startup(e); + } else { + throw new IllegalArgumentException("Unexpected StartupEntry entry count: " + all.length); + } + } catch (Exception ex) { + mh.errormsg("jshell.err.corrupted.stored.startup", ex.getMessage()); + } + } + return defaultStartup(mh); + } + + /** + * Factory method: Read Startup from a list of external files or resources. + * + * @param fns list of file/resource names to access + * @param context printable non-natural language context for errors + * @param mh handler for error messages + * @return files as Startup, or null when error (message has been printed) + */ + static Startup fromFileList(List fns, String context, MessageHandler mh) { + List entries = fns.stream() + .map(fn -> readFile(fn, context, mh)) + .collect(toList()); + if (entries.stream().anyMatch(sue -> sue == null)) { + return null; + } + return new Startup(entries); + } + + /** + * Read a external file or a resource. + * + * @param filename file/resource to access + * @param context printable non-natural language context for errors + * @param mh handler for error messages + * @return file as startup entry, or null when error (message has been printed) + */ + private static StartupEntry readFile(String filename, String context, MessageHandler mh) { + if (filename != null) { + try { + byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename)); + return new StartupEntry(false, filename, new String(encoded), + LocalDateTime.now().format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))); + } catch (AccessDeniedException e) { + mh.errormsg("jshell.err.file.not.accessible", context, filename, e.getMessage()); + } catch (NoSuchFileException e) { + String resource = getResource(filename); + if (resource != null) { + // Not found as file, but found as resource + return new StartupEntry(true, filename, resource); + } + mh.errormsg("jshell.err.file.not.found", context, filename); + } catch (Exception e) { + mh.errormsg("jshell.err.file.exception", context, filename, e); + } + } else { + mh.errormsg("jshell.err.file.filename", context); + } + return null; + + } + + /** + * Factory method: The empty Startup ("-none"). + * + * @return the empty Startup + */ + static Startup noStartup() { + return new Startup(Collections.emptyList()); + } + + /** + * Factory method: The default Startup ("-default."). + * + * @param mh handler for error messages + * @return The default Startup, or empty startup when error (message has been printed) + */ + static Startup defaultStartup(MessageHandler mh) { + if (defaultStartup != null) { + return defaultStartup; + } + try { + String content = readResource(DEFAULT_STARTUP_NAME); + return defaultStartup = new Startup( + new StartupEntry(true, DEFAULT_STARTUP_NAME, content)); + } catch (AccessDeniedException e) { + mh.errormsg("jshell.err.file.not.accessible", "jshell", DEFAULT_STARTUP_NAME, e.getMessage()); + } catch (NoSuchFileException e) { + mh.errormsg("jshell.err.file.not.found", "jshell", DEFAULT_STARTUP_NAME); + } catch (Exception e) { + mh.errormsg("jshell.err.file.exception", "jshell", DEFAULT_STARTUP_NAME, e); + } + return defaultStartup = noStartup(); + } + +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties index 6a4beda15b3..7042200d334 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties @@ -148,6 +148,8 @@ jshell.err.no.such.snippets = No such snippet: {0} jshell.err.the.snippet.cannot.be.used.with.this.command = This command does not accept the snippet ''{0}'' : {1} jshell.err.retained.mode.failure = Failure in retained modes (modes cleared) -- {0} {1} +jshell.err.corrupted.stored.startup = Corrupted stored startup, using default -- {0} + jshell.console.see.more = jshell.console.see.javadoc = jshell.console.see.help = diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT.jsh b/langtools/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT.jsh index 52e8ae36377..b65aada014a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT.jsh +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT.jsh @@ -8,4 +8,3 @@ import java.util.function.*; import java.util.prefs.*; import java.util.regex.*; import java.util.stream.*; - diff --git a/langtools/test/jdk/jshell/ToolCommandOptionTest.java b/langtools/test/jdk/jshell/ToolCommandOptionTest.java index 05a355d07f4..3bc3c2ee7b7 100644 --- a/langtools/test/jdk/jshell/ToolCommandOptionTest.java +++ b/langtools/test/jdk/jshell/ToolCommandOptionTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8157395 8157393 8157517 8158738 8167128 8163840 8167637 8170368 8172102 + * @bug 8157395 8157393 8157517 8158738 8167128 8163840 8167637 8170368 8172102 8172179 * @summary Tests of jshell comand options, and undoing operations * @modules jdk.jshell/jdk.internal.jshell.tool * jdk.compiler/com.sun.tools.javac.api @@ -273,14 +273,13 @@ public class ToolCommandOptionTest extends ReplToolTesting { (a) -> assertCommand(a, "/set start DEFAULT PRINTING", ""), (a) -> assertCommandOutputContains(a, "/set start", - "void println", "import java.util.*"), + "/set start DEFAULT PRINTING", "void println", "import java.util.*"), (a) -> assertCommand(a, "/set start " + startup.toString(), ""), - (a) -> assertCommand(a, "/set start", - "| startup.jsh:\n" + - "| int iAmHere = 1234;\n" + - "| \n" + - "| /set start startup.jsh"), + (a) -> assertCommandOutputContains(a, "/set start", + "| /set start " + startup + "\n" + + "| ---- " + startup + " @ ", " ----\n" + + "| int iAmHere = 1234;\n"), (a) -> assertCommand(a, "/se sta -no", ""), (a) -> assertCommand(a, "/set start", @@ -322,11 +321,18 @@ public class ToolCommandOptionTest extends ReplToolTesting { "| /set start -retain -none"), (a) -> assertCommand(a, "/set start -retain " + startup.toString(), ""), - (a) -> assertCommand(a, "/set start", - "| startup.jsh:\n" + - "| int iAmHere = 1234;\n" + - "| \n" + - "| /set start -retain startup.jsh") + (a) -> assertCommand(a, "/set start DEFAULT PRINTING", + ""), + (a) -> assertCommandOutputStartsWith(a, "/set start", + "| /set start -retain " + startup.toString() + "\n" + + "| /set start DEFAULT PRINTING\n" + + "| ---- " + startup.toString() + " @ "), + (a) -> assertCommandOutputContains(a, "/set start", + "| ---- DEFAULT ----\n", + "| ---- PRINTING ----\n", + "| int iAmHere = 1234;\n", + "| void println(String s)", + "| import java.io.*;") ); } From 362b794a8249487690b5a2fb3dfbe98cb121b23f Mon Sep 17 00:00:00 2001 From: Robert Field Date: Thu, 19 Jan 2017 11:17:11 -0800 Subject: [PATCH 07/16] 8171130: jshell tool: /edit adds empty statement to brace terminated snippet 8173007: JShell Tests: ToolFormatTest takes too long Reviewed-by: jlahoda --- .../jdk/internal/jshell/tool/JShellTool.java | 11 ++- .../test/jdk/jshell/ExternalEditorTest.java | 25 ++++++- langtools/test/jdk/jshell/ToolFormatTest.java | 69 ++++++++++++++++++- 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 94dcf3a52bf..8586c13621a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -2191,13 +2191,22 @@ public class JShellTool implements MessageHandler { case ASSIGNMENT_SUBKIND: case OTHER_EXPRESSION_SUBKIND: case TEMP_VAR_EXPRESSION_SUBKIND: - case STATEMENT_SUBKIND: case UNKNOWN_SUBKIND: if (!src.endsWith(";")) { src = src + ";"; } srcSet.add(src); break; + case STATEMENT_SUBKIND: + if (src.endsWith("}")) { + // Could end with block or, for example, new Foo() {...} + // so, we need deeper analysis to know if it needs a semicolon + src = analysis.analyzeCompletion(src).source(); + } else if (!src.endsWith(";")) { + src = src + ";"; + } + srcSet.add(src); + break; default: srcSet.add(src); break; diff --git a/langtools/test/jdk/jshell/ExternalEditorTest.java b/langtools/test/jdk/jshell/ExternalEditorTest.java index e38020e600c..1c421e268a7 100644 --- a/langtools/test/jdk/jshell/ExternalEditorTest.java +++ b/langtools/test/jdk/jshell/ExternalEditorTest.java @@ -24,7 +24,7 @@ /* * @test * @summary Testing external editor. - * @bug 8143955 8080843 8163816 8143006 8169828 + * @bug 8143955 8080843 8163816 8143006 8169828 8171130 * @modules jdk.jshell/jdk.internal.jshell.tool * @build ReplToolTesting CustomEditor EditorTestBase * @run testng ExternalEditorTest @@ -50,6 +50,7 @@ import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; public class ExternalEditorTest extends EditorTestBase { @@ -119,6 +120,28 @@ public class ExternalEditorTest extends EditorTestBase { super.testEditor(defaultStartup, args, t); } + @Test + public void testStatementSemicolonAddition() { + testEditor( + a -> assertCommand(a, "if (true) {}", ""), + a -> assertCommand(a, "if (true) {} else {}", ""), + a -> assertCommand(a, "Object o", "o ==> null"), + a -> assertCommand(a, "if (true) o = new Object() { int x; }", ""), + a -> assertCommand(a, "if (true) o = new Object() { int y; }", ""), + a -> assertCommand(a, "System.err.flush()", ""), // test still ; for expression statement + a -> assertEditOutput(a, "/ed", "", () -> { + assertEquals(getSource(), + "if (true) {}\n" + + "if (true) {} else {}\n" + + "Object o;\n" + + "if (true) o = new Object() { int x; };\n" + + "if (true) o = new Object() { int y; };\n" + + "System.err.flush();\n"); + exit(); + }) + ); + } + private static boolean isWindows() { return System.getProperty("os.name").startsWith("Windows"); } diff --git a/langtools/test/jdk/jshell/ToolFormatTest.java b/langtools/test/jdk/jshell/ToolFormatTest.java index 8e60db44941..1056f0abcee 100644 --- a/langtools/test/jdk/jshell/ToolFormatTest.java +++ b/langtools/test/jdk/jshell/ToolFormatTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8148316 8148317 8151755 8152246 8153551 8154812 8157261 8163840 8166637 8161969 + * @bug 8148316 8148317 8151755 8152246 8153551 8154812 8157261 8163840 8166637 8161969 8173007 * @summary Tests for output customization * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -38,8 +38,6 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -140,6 +138,66 @@ public class ToolFormatTest extends ReplToolTesting { ); } + public void testSetFormatSelectorSample() { + test( + (a) -> assertCommandOutputStartsWith(a, "/set mode ate -quiet", + "| Created new feedback mode: ate"), + (a) -> assertCommand(a, "/set feedback ate", ""), + + (a) -> assertCommand(a, "/set format ate display '---replaced,modified,added-primary---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++replaced,modified,added-primary+++' replaced,modified,added-primary", ""), + (a) -> assertCommand(a, "\"replaced,modified,added-primary\"", "+++replaced,modified,added-primary+++"), + + (a) -> assertCommand(a, "/set format ate display '---added-primary,update---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++added-primary,update+++' added-primary,update", ""), + (a) -> assertCommand(a, "\"added-primary,update\"", "+++added-primary,update+++"), + + + (a) -> assertCommand(a, "/set format ate display '---method-replaced-primary---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++method-replaced-primary+++' method-replaced-primary", ""), + (a) -> assertCommand(a, "\"method-replaced-primary\"", "---method-replaced-primary---"), + + (a) -> assertCommand(a, "/set format ate display '---method-replaced-update---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++method-replaced-update+++' method-replaced-update", ""), + (a) -> assertCommand(a, "\"method-replaced-update\"", "---method-replaced-update---"), + + (a) -> assertCommand(a, "/set format ate display '---method-added-update---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++method-added-update+++' method-added-update", ""), + (a) -> assertCommand(a, "\"method-added-update\"", "---method-added-update---"), + + (a) -> assertCommand(a, "/set format ate display '---method-added---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++method-added+++' method-added", ""), + (a) -> assertCommand(a, "\"method-added\"", "---method-added---"), + + (a) -> assertCommand(a, "/set format ate display '---class-modified,added-primary,update---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++class-modified,added-primary,update+++' class-modified,added-primary,update", ""), + (a) -> assertCommand(a, "\"class-modified,added-primary,update\"", "---class-modified,added-primary,update---"), + + (a) -> assertCommand(a, "/set format ate display '---class-modified,added-primary---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++class-modified,added-primary+++' class-modified,added-primary", ""), + (a) -> assertCommand(a, "\"class-modified,added-primary\"", "---class-modified,added-primary---"), + + (a) -> assertCommand(a, "/set format ate display '---class-modified,added-update---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++class-modified,added-update+++' class-modified,added-update", ""), + (a) -> assertCommand(a, "\"class-modified,added-update\"", "---class-modified,added-update---"), + + (a) -> assertCommand(a, "/set format ate display '---replaced,added---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++replaced,added+++' replaced,added", ""), + (a) -> assertCommand(a, "\"replaced,added\"", "+++replaced,added+++"), + + (a) -> assertCommand(a, "/set format ate display '---replaced-primary,update---'", ""), + (a) -> assertCommand(a, "/set format ate display '+++replaced-primary,update+++' replaced-primary,update", ""), + (a) -> assertCommand(a, "\"replaced-primary,update\"", "---replaced-primary,update---"), + + (a) -> assertCommandOutputStartsWith(a, "/set feedback normal", "| Feedback mode: normal") + ); + } + + // This test is exhaustive and takes to long for routine testing -- disabled. + // A sampling of these has been added (above: testSetFormatSelectorSample). + // See 8173007 + // Save for possible future deep testing or debugging + @Test(enabled = false) public void testSetFormatSelector() { List tests = new ArrayList<>(); tests.add((a) -> assertCommandOutputStartsWith(a, "/set mode ate -quiet", @@ -202,6 +260,11 @@ public class ToolFormatTest extends ReplToolTesting { tests.add((a) -> assertCommand(a, "/set format ate display '" + no + "'", "")); tests.add((a) -> assertCommand(a, "/set format ate display '" + yes + "' " + select, "")); tests.add((a) -> assertCommand(a, "\"" + select + "\"", expect)); + /**** for sample generation **** + System.err.println(" (a) -> assertCommand(a, \"/set format ate display '" + no + "'\", \"\"),"); + System.err.println(" (a) -> assertCommand(a, \"/set format ate display '" + yes + "' " + select + "\", \"\"),"); + System.err.println(" (a) -> assertCommand(a, \"\\\"" + select + "\\\"\", \"" + expect + "\"),\n"); + ****/ } } } From 8045fb0059f479015ff1365203f569cb256e08fc Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Thu, 19 Jan 2017 13:16:19 -0800 Subject: [PATCH 08/16] 8169608: Compiler Tree API's Doctrees.getDocTreePath needs to accept a PackageElement 8157611: field visiblePackages is null for the unnamed module producing NPE when accessed Reviewed-by: jjg, jlahoda --- .../classes/com/sun/source/util/DocTrees.java | 20 ++-- .../com/sun/tools/javac/api/JavacTrees.java | 23 +--- .../com/sun/tools/javac/code/Symbol.java | 2 + .../doclets/toolkit/CommentUtils.java | 49 +++++---- .../internal/doclets/toolkit/WorkArounds.java | 24 +++-- .../javadoc/internal/tool/ElementsTable.java | 11 +- .../internal/tool/JavadocClassFinder.java | 3 +- .../internal/tool/ToolEnvironment.java | 17 +-- .../javadoc/tool/treeapi/TestDocTrees.java | 100 ++++++++++++++++++ .../jdk/javadoc/tool/treeapi/overview.html | 27 +++++ .../dcapi/DocCommentTreeApiTester.java | 54 +++++++++- 11 files changed, 250 insertions(+), 80 deletions(-) create mode 100644 langtools/test/jdk/javadoc/tool/treeapi/TestDocTrees.java create mode 100644 langtools/test/jdk/javadoc/tool/treeapi/overview.html diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java index 6b4b55d8977..1c0a3ec9895 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -31,6 +31,7 @@ import java.util.List; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; import javax.tools.Diagnostic; import javax.tools.FileObject; import javax.tools.JavaCompiler.CompilationTask; @@ -127,17 +128,22 @@ public abstract class DocTrees extends Trees { /** * Returns a doc tree path containing the doc comment tree of the given file. - * The file must be an HTML file, in which case the doc comment tree represents the - * contents of the <body> tag, and any enclosing tags are ignored. + * The file must be an HTML file, in which case the doc comment tree represents + * the contents of the {@code } tag, and any enclosing tags are ignored. + * Any references to source code elements contained in {@code @see} and + * {@code {@link}} tags in the doc comment tree will be evaluated in the + * context of the given package element. * Returns {@code null} if no doc comment was found. - * Future releases may support additional file types. * - * @param fileObject the content container - * @return a doc tree path containing the doc comment read from the given file. + * @param fileObject a file object encapsulating the HTML content + * @param packageElement a package element to associate with the given file object + * representing a legacy package.html, null otherwise + * @return a doc tree path containing the doc comment parsed from the given file + * @throws IllegalArgumentException if the fileObject is not an HTML file * * @since 9 */ - public abstract DocTreePath getDocTreePath(FileObject fileObject); + public abstract DocTreePath getDocTreePath(FileObject fileObject, PackageElement packageElement); /** * Returns the language model element referred to by the leaf node of the given diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java index 2edfcb1b3b8..32b21139f40 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java @@ -174,7 +174,6 @@ public class JavacTrees extends DocTrees { private JavaFileManager fileManager; private ParserFactory parser; private Symtab syms; - private Map javaFileObjectToPackageMap; // called reflectively from Trees.instance(CompilationTask task) public static JavacTrees instance(JavaCompiler.CompilationTask task) { @@ -198,7 +197,6 @@ public class JavacTrees extends DocTrees { } protected JavacTrees(Context context) { - javaFileObjectToPackageMap = new HashMap<>(); this.breakIterator = null; context.put(JavacTrees.class, this); init(context); @@ -1039,10 +1037,11 @@ public class JavacTrees extends DocTrees { } @Override @DefinedBy(Api.COMPILER_TREE) - public DocTreePath getDocTreePath(FileObject fileObject) { + public DocTreePath getDocTreePath(FileObject fileObject, PackageElement packageElement) { JavaFileObject jfo = asJavaFileObject(fileObject); DocCommentTree docCommentTree = getDocCommentTree(jfo); - return new DocTreePath(makeTreePath(jfo, docCommentTree), docCommentTree); + TreePath treePath = makeTreePath((PackageSymbol)packageElement, jfo, docCommentTree); + return new DocTreePath(treePath, docCommentTree); } @Override @DefinedBy(Api.COMPILER_TREE) @@ -1160,17 +1159,8 @@ public class JavacTrees extends DocTrees { } } - /** - * Register a file object, such as for a package.html, that provides - * doc comments for a package. - * @param psym the PackageSymbol representing the package. - * @param jfo the JavaFileObject for the given package. - */ - public void putJavaFileObject(PackageSymbol psym, JavaFileObject jfo) { - javaFileObjectToPackageMap.putIfAbsent(jfo, psym); - } - - private TreePath makeTreePath(final JavaFileObject jfo, DocCommentTree dcTree) { + private TreePath makeTreePath(final PackageSymbol psym, final JavaFileObject jfo, + DocCommentTree dcTree) { JCCompilationUnit jcCompilationUnit = new JCCompilationUnit(List.nil()) { public int getPos() { return Position.FIRSTPOS; @@ -1191,9 +1181,6 @@ public class JavacTrees extends DocTrees { } }; - PackageSymbol psym = javaFileObjectToPackageMap.getOrDefault(jfo, - syms.unnamedModule.unnamedPackage); - jcCompilationUnit.docComments = new DocCommentTable() { @Override public boolean hasComment(JCTree tree) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index 046d333ad80..39d2316f0fc 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -1070,6 +1070,8 @@ public abstract class Symbol extends AnnoConstruct implements Element { public Name fullname; public ClassSymbol package_info; // see bug 6443073 public ModuleSymbol modle; + // the file containing the documentation comments for the package + public JavaFileObject sourcefile; public PackageSymbol(Name name, Type type, Symbol owner) { super(PCK, 0, name, type, owner); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java index 7b813cbde50..d9f6c38f1bb 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -35,6 +35,19 @@ package jdk.javadoc.internal.doclets.toolkit; import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Name; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.util.Elements; +import javax.tools.FileObject; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; import com.sun.source.doctree.DocCommentTree; import com.sun.source.doctree.DocTree; @@ -45,22 +58,6 @@ import com.sun.source.util.DocTreeFactory; import com.sun.source.util.DocTreePath; import com.sun.source.util.DocTrees; import com.sun.source.util.TreePath; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Name; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.util.Elements; -import javax.tools.FileObject; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; - import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy.Api; import jdk.javadoc.internal.doclets.toolkit.util.Utils; @@ -177,10 +174,18 @@ public class CommentUtils { */ public DocCommentDuo getHtmlCommentDuo(Element e) { FileObject fo = null; - if (e.getKind().equals(ElementKind.OTHER)) { - fo = configuration.getOverviewPath(); - } else if (e.getKind().equals(ElementKind.PACKAGE)) { - fo = configuration.workArounds.getJavaFileObject((PackageElement)e); + PackageElement pe = null; + switch (e.getKind()) { + case OTHER: + fo = configuration.getOverviewPath(); + pe = configuration.workArounds.getUnnamedPackage(); + break; + case PACKAGE: + fo = configuration.workArounds.getJavaFileObject((PackageElement)e); + pe = (PackageElement)e; + break; + default: + return null; } if (fo == null) { return null; @@ -190,7 +195,7 @@ public class CommentUtils { if (dcTree == null) { return null; } - DocTreePath treePath = trees.getDocTreePath(fo); + DocTreePath treePath = trees.getDocTreePath(fo, pe); return new DocCommentDuo(treePath.getTreePath(), dcTree); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java index 74908eeffa2..50ffb6bafef 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java @@ -44,6 +44,7 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; +import javax.tools.FileObject; import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; @@ -59,7 +60,9 @@ import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.ModuleSymbol; +import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; +import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.comp.AttrContext; import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.model.JavacElements; @@ -192,11 +195,24 @@ public class WorkArounds { return ((VarSymbol)ve).getConstValue(); } - //TODO: DocTrees: Trees.getPath(Element e) is slow a factor 4-5 times. + // TODO: DocTrees: Trees.getPath(Element e) is slow a factor 4-5 times. public Map getElementToTreePath() { return toolEnv.elementToTreePath; } + // TODO: we need ElementUtils.getPackage to cope with input strings + // to return the proper unnamedPackage for all supported releases. + PackageElement getUnnamedPackage() { + return (toolEnv.source.allowModules()) + ? toolEnv.syms.unnamedModule.unnamedPackage + : toolEnv.syms.noModule.unnamedPackage; + } + + // TODO: implement in either jx.l.m API (preferred) or DocletEnvironment. + FileObject getJavaFileObject(PackageElement packageElement) { + return ((PackageSymbol)packageElement).sourcefile; + } + // TODO: needs to ported to jx.l.m. public TypeElement searchClass(TypeElement klass, String className) { // search by qualified name first @@ -530,12 +546,6 @@ public class WorkArounds { } } - // TODO: this is a fast way to get the JavaFileObject for - // a package.html file, however we need to eliminate this. - public JavaFileObject getJavaFileObject(PackageElement pe) { - return toolEnv.pkgToJavaFOMap.get(pe); - } - // TODO: we need to eliminate this, as it is hacky. /** * Returns a representation of the package truncated to two levels. diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java index 6c37e1f17a1..5b1a8e72785 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -39,14 +39,12 @@ import java.util.Set; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.ModuleElement; import javax.lang.model.element.ModuleElement.ExportsDirective; import javax.lang.model.element.ModuleElement.RequiresDirective; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.SimpleElementVisitor9; import javax.tools.JavaFileManager; @@ -54,15 +52,12 @@ import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; import javax.tools.StandardLocation; -import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Kinds.Kind; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.CompletionFailure; -import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.ModuleSymbol; import com.sun.tools.javac.code.Symbol.PackageSymbol; -import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.comp.Modules; import com.sun.tools.javac.tree.JCTree.JCClassDecl; @@ -75,9 +70,11 @@ import jdk.javadoc.doclet.DocletEnvironment; import jdk.javadoc.doclet.DocletEnvironment.ModuleMode; import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; +import static javax.tools.JavaFileObject.Kind.*; import static jdk.javadoc.internal.tool.Main.Result.*; import static jdk.javadoc.internal.tool.JavadocTool.isValidClassName; + /** * This class manages elements specified on the command line, and * produces "specified" and "included" data sets, needed by the @@ -864,7 +861,7 @@ public class ElementsTable { } private boolean isTypeElementSelected(TypeElement te) { - return (xclasses || toolEnv.isFromSource(te)) && isSelected(te); + return (xclasses || toolEnv.getFileKind(te) == SOURCE) && isSelected(te); } SimpleElementVisitor9 visibleElementVisitor = null; diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java index e554d393d05..5f464addfab 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java @@ -88,8 +88,7 @@ public class JavadocClassFinder extends ClassFinder { @Override protected void extraFileActions(PackageSymbol pack, JavaFileObject fo) { if (fo.isNameCompatible("package", JavaFileObject.Kind.HTML)) { - toolEnv.pkgToJavaFOMap.put(pack, fo); - trees.putJavaFileObject(pack, fo); + pack.sourcefile = fo; } } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java index 31719c60725..22550d0d943 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -29,7 +29,6 @@ package jdk.javadoc.internal.tool; import java.util.*; import javax.lang.model.element.Element; -import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.tools.JavaFileManager; @@ -116,8 +115,6 @@ public class ToolEnvironment { WeakHashMap treePaths = new WeakHashMap<>(); - public final HashMap pkgToJavaFOMap = new HashMap<>(); - /** Allow documenting from class files? */ boolean docClasses = false; @@ -193,21 +190,11 @@ public class ToolEnvironment { elementToTreePath.put(e, tree); } - /** - * Returns true if the type element originates from source. - * Primarily used to disambiguate a type element associated with a source - * file versus a class file. - * @param te the type element - * @return true if the symbol is from source - */ - public boolean isFromSource(TypeElement te) { - return getFileKind(te) == Kind.SOURCE; - } - public Kind getFileKind(TypeElement te) { JavaFileObject jfo = ((ClassSymbol)te).outermostClass().classfile; return jfo == null ? Kind.SOURCE : jfo.getKind(); } + /** * Print a notice, iff quiet is not specified. * diff --git a/langtools/test/jdk/javadoc/tool/treeapi/TestDocTrees.java b/langtools/test/jdk/javadoc/tool/treeapi/TestDocTrees.java new file mode 100644 index 00000000000..1758a926ff3 --- /dev/null +++ b/langtools/test/jdk/javadoc/tool/treeapi/TestDocTrees.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, 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 + * @bug 8157611 + * @summary test DocTrees is working correctly relative to HTML access + * @modules + * jdk.javadoc/jdk.javadoc.internal.api + * jdk.javadoc/jdk.javadoc.internal.tool + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @library /tools/lib + * @build toolbox.ToolBox toolbox.TestRunner + * @run main TestDocTrees + */ + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import toolbox.*; +import toolbox.Task.Expect; + +import static toolbox.Task.OutputKind.*; + +/** + * This class is used to test DocTrees functionality relating to + * package and overview HTML files. + */ +public class TestDocTrees extends TestRunner { + final ToolBox tb; + final File testFile; + final File testSrc; + final File overviewFile; + + TestDocTrees() throws IOException { + super(System.err); + tb = new ToolBox(); + testSrc = new File(System.getProperty("test.src")); + testFile = new File(testSrc, "TestDocTrees.java"); + overviewFile = new File(testSrc, "overview.html"); + } + + protected void runTests() throws Exception { + runTests(m -> new Object[]{Paths.get(m.getName())}); + } + + public static void main(String... args) throws Exception { + new TestDocTrees().runTests(); + } + + @Test + public void testOverviewWithRelease8(Path out) { + execTask("-d", out.toString(), + "--release", "8", + "-Xdoclint:all", + "-Xdoclint:-missing", + "-sourcepath", testSrc.getAbsolutePath(), + testFile.getAbsolutePath(), + "-overview", overviewFile.getAbsolutePath()); + } + + @Test + public void testOverviewWithoutRelease(Path out) throws Exception { + execTask("-d", out.toString(), + "-Xdoclint:all", + "-Xdoclint:-missing", + "-sourcepath", testSrc.getAbsolutePath(), + testFile.getAbsolutePath(), + "-overview", overviewFile.getAbsolutePath()); + } + + private Task.Result execTask(String... args) { + JavadocTask et = new JavadocTask(tb, Task.Mode.CMDLINE); + //args.forEach((a -> System.err.println("arg: " + a))); + return et.options(args).run(); + } +} diff --git a/langtools/test/jdk/javadoc/tool/treeapi/overview.html b/langtools/test/jdk/javadoc/tool/treeapi/overview.html new file mode 100644 index 00000000000..d825975f0be --- /dev/null +++ b/langtools/test/jdk/javadoc/tool/treeapi/overview.html @@ -0,0 +1,27 @@ + + + + {@link omg.what.gives} + + \ No newline at end of file diff --git a/langtools/test/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java b/langtools/test/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java index 13cb2234a56..71cb78ced62 100644 --- a/langtools/test/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java +++ b/langtools/test/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8132096 + * @bug 8132096 8157611 * @summary test the APIs in the DocTree interface * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.file @@ -48,12 +48,15 @@ import java.util.List; import java.util.Locale; import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.util.Elements; import javax.tools.FileObject; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import com.sun.source.doctree.DocTree; import com.sun.source.doctree.DocCommentTree; +import com.sun.source.util.DocTreePath; import com.sun.source.util.DocTrees; import com.sun.source.util.JavacTask; import com.sun.tools.javac.api.JavacTool; @@ -90,6 +93,9 @@ public class DocCommentTreeApiTester { // tests files relative path in an unnamed package test.runRelativePathTest("OverviewTest.java", "overview0.html"); + // tests doctreepath using package element and package.html + test.runDocTreePath("pkg/Anchor.java", "package.html"); + // test for correct parsing using valid and some invalid html tags for (int i = 0; i < 7; i++) { String hname = "overview" + i + ".html"; @@ -152,6 +158,7 @@ public class DocCommentTreeApiTester { } } } + /** * Tests DocTrees.getDocCommentTree(Element e, String relpath) using relative path. * @@ -219,6 +226,49 @@ public class DocCommentTreeApiTester { } } + /** + * Tests DocTrees.getDocTreePath(PackageElement p, FileObject fo). + * + * @param javaFileName the java anchor file + * @param pkgFileName the package file name + * @throws Exception e if something goes awry + */ + public void runDocTreePath(String javaFileName, String pkgFileName) throws Exception { + List javaFiles = new ArrayList<>(); + javaFiles.add(new File(testSrc, javaFileName)); + + List dirs = new ArrayList<>(); + dirs.add(new File(testSrc)); + + try (StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null)) { + fm.setLocation(javax.tools.StandardLocation.SOURCE_PATH, dirs); + Iterable fos = fm.getJavaFileObjectsFromFiles(javaFiles); + + final JavacTask t = javac.getTask(null, fm, null, null, null, fos); + final DocTrees trees = DocTrees.instance(t); + final Elements elementUtils = t.getElements(); + + Iterable elements = t.analyze(); + + Element klass = elements.iterator().next(); + PackageElement pkg = elementUtils.getPackageOf(klass); + + FileObject htmlFo = fm.getFileForInput(javax.tools.StandardLocation.SOURCE_PATH, + t.getElements().getPackageOf(klass).getQualifiedName().toString(), + "package.html"); + System.out.println(); + DocTreePath treePath = trees.getDocTreePath(htmlFo, pkg); + DocCommentTree dcTree = treePath.getDocComment(); + + StringWriter sw = new StringWriter(); + printer.print(dcTree, sw); + String found = sw.toString(); + + String expected = getExpected(htmlFo.openReader(true)); + astcheck(pkgFileName, expected, found); + } + } + void astcheck(String testinfo, String expected, String found) { System.err.print("ASTChecker: " + testinfo); check0(expected, found); From f54232896cc89647b9cd92958e9ed2cf00ab9520 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 19 Jan 2017 14:35:16 -0800 Subject: [PATCH 09/16] 8172753: Improve style of left-side index pages Reviewed-by: bpatel --- .../internal/doclets/toolkit/resources/stylesheet.css | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css index b12d57dc17c..98aec12202a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css @@ -250,17 +250,19 @@ Page header and footer styles padding:5px 0 0 0; } .indexNav { - margin:10px; position:relative; + font-size:12px; + background-color:#dee3e9; } .indexNav ul { - padding:0; - margin:0; + margin-top:0; + padding:5px; } .indexNav ul li { display:inline; list-style-type:none; padding-right:10px; + text-transform:uppercase; } .indexNav h1 { font-size:13px; From 16d379dad4995b7a032b537cee4e59957aaa4e8a Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 19 Jan 2017 15:12:59 -0800 Subject: [PATCH 10/16] 8165102: incorrect message from javac Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Modules.java | 36 +++++++--- .../com/sun/tools/javac/file/Locations.java | 4 +- .../tools/javac/resources/compiler.properties | 6 ++ langtools/test/tools/javac/diags/Example.java | 22 +++--- .../DirPathElementNotDirectory.java | 4 +- .../ModuleNotOnModuleSourcePath.java | 25 +++++++ .../modulesourcepath/m/extra/module-info.java | 24 +++++++ .../NotInModuleOnModuleSourcePath.java | 27 ++++++++ .../modulesourcepath/m/module-info.java | 25 +++++++ .../UnnamedPackageInNamedModule.java | 4 +- .../ModulesAndModuleSourcePathTest.java | 67 +++++++++++++++++++ .../javac/modules/MultiModuleModeTest.java | 4 +- 12 files changed, 219 insertions(+), 29 deletions(-) create mode 100644 langtools/test/tools/javac/diags/examples/ModuleNotOnModuleSourcePath/ModuleNotOnModuleSourcePath.java create mode 100644 langtools/test/tools/javac/diags/examples/ModuleNotOnModuleSourcePath/modulesourcepath/m/extra/module-info.java create mode 100644 langtools/test/tools/javac/diags/examples/NotInModuleOnModuleSourcePath/NotInModuleOnModuleSourcePath.java create mode 100644 langtools/test/tools/javac/diags/examples/NotInModuleOnModuleSourcePath/modulesourcepath/m/module-info.java create mode 100644 langtools/test/tools/javac/modules/ModulesAndModuleSourcePathTest.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java index 3add15e8909..4e3eaa82d9b 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2017, 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 @@ -374,6 +374,9 @@ public class Modules extends JCTree.Visitor { log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name)); } } else { + if (tree.getPackage() == null) { + log.error(tree.pos(), Errors.UnnamedPkgNotAllowedNamedModules); + } msym = syms.enterModule(name); } if (msym.sourceLocation == null) { @@ -388,7 +391,11 @@ public class Modules extends JCTree.Visitor { } else if (c != null && c.packge().modle == syms.unnamedModule) { tree.modle = syms.unnamedModule; } else { - log.error(tree.pos(), Errors.UnnamedPkgNotAllowedNamedModules); + if (tree.getModuleDecl() != null) { + log.error(tree.pos(), Errors.ModuleNotFoundOnModuleSourcePath); + } else { + log.error(tree.pos(), Errors.NotInModuleOnModuleSourcePath); + } tree.modle = syms.errModule; } } catch (IOException e) { @@ -457,19 +464,27 @@ public class Modules extends JCTree.Visitor { } } + /** + * Determine the location for the module on the module source path + * or source output directory which contains a given CompilationUnit. + * If the source output directory is unset, the class output directory + * will be checked instead. + * {@code null} is returned if no such module can be found. + * @param tree the compilation unit tree + * @return the location for the enclosing module + * @throws IOException if there is a problem while searching for the module. + */ private Location getModuleLocation(JCCompilationUnit tree) throws IOException { + Name pkgName; if (tree.getModuleDecl() != null) { - return getModuleLocation(tree.sourcefile, null); - } else if (tree.getPackage() != null) { - JCPackageDecl pkg = tree.getPackage(); - return getModuleLocation(tree.sourcefile, TreeInfo.fullName(pkg.pid)); + pkgName = null; } else { - // code in unnamed module - return null; + JCPackageDecl pkg = tree.getPackage(); + pkgName = (pkg == null) ? names.empty : TreeInfo.fullName(pkg.pid); } - } - private Location getModuleLocation(JavaFileObject fo, Name pkgName) throws IOException { + JavaFileObject fo = tree.sourcefile; + // For now, just check module source path. // We may want to check source path as well. Location loc = @@ -482,7 +497,6 @@ public class Modules extends JCTree.Visitor { fileManager.getLocationForModule(sourceOutput, fo, (pkgName == null) ? null : pkgName.toString()); } - return loc; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java index d6df913de38..f0fa2277d44 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -553,7 +553,7 @@ public class Locations { @Override Location getLocationForModule(Path dir) { - return pathLocations.get(dir); + return (pathLocations == null) ? null : pathLocations.get(dir); } private boolean listed; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 5da57e1e35c..189a398d3ec 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -2845,6 +2845,12 @@ compiler.warn.module.not.found=\ compiler.err.too.many.modules=\ too many module declarations found +compiler.err.module.not.found.on.module.source.path=\ + module not found on module source path + +compiler.err.not.in.module.on.module.source.path=\ + not in a module on the module source path + # 0: symbol compiler.err.duplicate.module=\ duplicate module: {0} diff --git a/langtools/test/tools/javac/diags/Example.java b/langtools/test/tools/javac/diags/Example.java index bf0b9c3f38a..72c4b64e382 100644 --- a/langtools/test/tools/javac/diags/Example.java +++ b/langtools/test/tools/javac/diags/Example.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2017, 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 @@ -66,6 +66,7 @@ class Example implements Comparable { modulePathFiles = new ArrayList(); classPathFiles = new ArrayList(); additionalFiles = new ArrayList(); + nonEmptySrcFiles = new ArrayList(); findFiles(file, srcFiles); for (File f: srcFiles) { @@ -99,11 +100,11 @@ class Example implements Comparable { } } } else if (f.isFile()) { - if (f.getName().endsWith(".java")) { - files.add(f); - } else if (f.getName().equals("modulesourcepath")) { - moduleSourcePathDir = f; - } + if (f.getName().endsWith(".java")) { + files.add(f); + } else if (f.getName().equals("modulesourcepath")) { + moduleSourcePathDir = f; + } } } @@ -132,8 +133,10 @@ class Example implements Comparable { foundInfo(f); runOpts = Arrays.asList(runMatch.group(1).trim().split(" +")); } - if (javaPat.matcher(line).matches()) + if (javaPat.matcher(line).matches()) { + nonEmptySrcFiles.add(f); break; + } } } catch (IOException e) { throw new Error(e); @@ -264,7 +267,9 @@ class Example implements Comparable { if (moduleSourcePathDir != null) { opts.add("--module-source-path"); opts.add(moduleSourcePathDir.getPath()); - files = moduleSourcePathFiles; + files = new ArrayList<>(); + files.addAll(moduleSourcePathFiles); + files.addAll(nonEmptySrcFiles); // srcFiles containing declarations } if (additionalFiles.size() > 0) { @@ -344,6 +349,7 @@ class Example implements Comparable { List modulePathFiles; List classPathFiles; List additionalFiles; + List nonEmptySrcFiles; File infoFile; private List runOpts; private List options; diff --git a/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/DirPathElementNotDirectory.java b/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/DirPathElementNotDirectory.java index 9fb276d932e..eef03129995 100644 --- a/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/DirPathElementNotDirectory.java +++ b/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/DirPathElementNotDirectory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -24,5 +24,3 @@ // key: compiler.warn.dir.path.element.not.directory // options: -Xlint:path // run: simple - -class DirPathElementNotDirectory { } diff --git a/langtools/test/tools/javac/diags/examples/ModuleNotOnModuleSourcePath/ModuleNotOnModuleSourcePath.java b/langtools/test/tools/javac/diags/examples/ModuleNotOnModuleSourcePath/ModuleNotOnModuleSourcePath.java new file mode 100644 index 00000000000..027d71381de --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleNotOnModuleSourcePath/ModuleNotOnModuleSourcePath.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017, 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.err.module.not.found.on.module.source.path + diff --git a/langtools/test/tools/javac/diags/examples/ModuleNotOnModuleSourcePath/modulesourcepath/m/extra/module-info.java b/langtools/test/tools/javac/diags/examples/ModuleNotOnModuleSourcePath/modulesourcepath/m/extra/module-info.java new file mode 100644 index 00000000000..5ef15da68a4 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleNotOnModuleSourcePath/modulesourcepath/m/extra/module-info.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, 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. + */ + +module m { } diff --git a/langtools/test/tools/javac/diags/examples/NotInModuleOnModuleSourcePath/NotInModuleOnModuleSourcePath.java b/langtools/test/tools/javac/diags/examples/NotInModuleOnModuleSourcePath/NotInModuleOnModuleSourcePath.java new file mode 100644 index 00000000000..f9389fcdd50 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/NotInModuleOnModuleSourcePath/NotInModuleOnModuleSourcePath.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, 2017, 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.err.not.in.module.on.module.source.path + +package p; class C { } + diff --git a/langtools/test/tools/javac/diags/examples/NotInModuleOnModuleSourcePath/modulesourcepath/m/module-info.java b/langtools/test/tools/javac/diags/examples/NotInModuleOnModuleSourcePath/modulesourcepath/m/module-info.java new file mode 100644 index 00000000000..c63ed483f51 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/NotInModuleOnModuleSourcePath/modulesourcepath/m/module-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017, 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. + */ + +module m { } + diff --git a/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/UnnamedPackageInNamedModule.java b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/UnnamedPackageInNamedModule.java index ed94f3e85fb..5f9a50f3430 100644 --- a/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/UnnamedPackageInNamedModule.java +++ b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/UnnamedPackageInNamedModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -22,5 +22,3 @@ */ // key: compiler.err.unnamed.pkg.not.allowed.named.modules - -class UnnamedPackageInNamedModule {} diff --git a/langtools/test/tools/javac/modules/ModulesAndModuleSourcePathTest.java b/langtools/test/tools/javac/modules/ModulesAndModuleSourcePathTest.java new file mode 100644 index 00000000000..6b54a74f5cf --- /dev/null +++ b/langtools/test/tools/javac/modules/ModulesAndModuleSourcePathTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, 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 8165102 + * @summary incorrect message from javac + * @library /tools/lib + * @modules + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase + * @run main ModulesAndModuleSourcePathTest + */ + +import java.nio.file.Files; +import java.nio.file.Path; + +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class ModulesAndModuleSourcePathTest extends ModuleTestBase { + public static void main(String... args) throws Exception { + ModulesAndModuleSourcePathTest t = new ModulesAndModuleSourcePathTest(); + t.runTests(); + } + + @Test + public void testModuleNotInModuleSrcPath(Path base) throws Exception { + Path src = base.resolve("src"); + Path m = src.resolve("m"); + Path extra = m.resolve("extra"); + tb.writeJavaFiles(extra, "module m {}"); + Path classes = base.resolve("classes"); + Files.createDirectories(classes); + + String log = new JavacTask(tb) + .options("-XDrawDiagnostics", "--module-source-path", src.toString()) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + if (!log.contains("module-info.java:1:1: compiler.err.module.not.found.on.module.source.path")) + throw new Exception("expected output not found"); + } +} diff --git a/langtools/test/tools/javac/modules/MultiModuleModeTest.java b/langtools/test/tools/javac/modules/MultiModuleModeTest.java index 437a675bea3..ffed1e00f04 100644 --- a/langtools/test/tools/javac/modules/MultiModuleModeTest.java +++ b/langtools/test/tools/javac/modules/MultiModuleModeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -90,7 +90,7 @@ public class MultiModuleModeTest extends ModuleTestBase { .writeAll() .getOutput(Task.OutputKind.DIRECT); - if (!log.contains("C.java:1:1: compiler.err.unnamed.pkg.not.allowed.named.modules")) + if (!log.contains("C.java:1:1: compiler.err.not.in.module.on.module.source.path")) throw new Exception("expected output not found"); } From 04405c6abc39622d7c64f669746560099f2a24f5 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 19 Jan 2017 19:14:51 -0800 Subject: [PATCH 11/16] 8147414: java.nio.file.ClosedFileSystemException in javadoc Reviewed-by: vromero --- .../com/sun/tools/javac/jvm/ClassReader.java | 7 +- .../classreader/FileSystemClosedTest.java | 124 ++++++++++++++++++ .../test/tools/javadoc/8147801/T8147801.java | 40 ++++-- .../javadoc/8147801/jarsrc/lib/Lib2.java | 4 +- 4 files changed, 157 insertions(+), 18 deletions(-) create mode 100644 langtools/test/tools/javac/classreader/FileSystemClosedTest.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index ca04575328c..433c3a2e39e 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -29,6 +29,7 @@ import java.io.*; import java.net.URI; import java.net.URISyntaxException; import java.nio.CharBuffer; +import java.nio.file.ClosedFileSystemException; import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; @@ -2756,8 +2757,8 @@ public class ClassReader { currentModule.provides = List.nil(); } } - } catch (IOException ex) { - throw badClassFile("unable.to.access.file", ex.getMessage()); + } catch (IOException | ClosedFileSystemException ex) { + throw badClassFile("unable.to.access.file", ex.toString()); } catch (ArrayIndexOutOfBoundsException ex) { throw badClassFile("bad.class.file", c.flatname); } finally { diff --git a/langtools/test/tools/javac/classreader/FileSystemClosedTest.java b/langtools/test/tools/javac/classreader/FileSystemClosedTest.java new file mode 100644 index 00000000000..15f3416cd4e --- /dev/null +++ b/langtools/test/tools/javac/classreader/FileSystemClosedTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2016, 2017, 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 + * @bug 8147414 + * @summary java.nio.file.ClosedFileSystemException in javadoc + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.JarTask toolbox.JavacTask toolbox.ToolBox + * @run main FileSystemClosedTest + */ + +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.ClosedFileSystemException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; + +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.Elements; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import toolbox.ToolBox; +import toolbox.JarTask; +import toolbox.JavacTask; + +public class FileSystemClosedTest { + public static void main(String... args) throws Exception { + new FileSystemClosedTest().run(); + } + + void run() throws Exception { + ToolBox tb = new ToolBox(); + Path jar = createJar(tb); + + Path src = Paths.get("src"); + tb.writeJavaFiles(src, "class C { p1.C1 c1; }"); + + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + PrintWriter out = new PrintWriter(System.err, true); + StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + List options = Arrays.asList("-classpath", jar.toString()); + Iterable files = fm.getJavaFileObjects(src.resolve("C.java")); + com.sun.source.util.JavacTask task = + (com.sun.source.util.JavacTask) comp.getTask(out, fm, null, options, null, files); + task.parse(); + + Elements elems = task.getElements(); + + try { + // Use p1, p1.C1 as a control to verify normal behavior + PackageElement p1 = elems.getPackageElement("p1"); + TypeElement p1C1 = elems.getTypeElement("p1.C1"); + System.err.println("p1: " + p1 + "; p1C1: " + p1C1); + if (p1C1 == null) { + throw new Exception("p1.C1 not found"); + } + + // Now repeat for p2, p2.C2, closing the file manager early + PackageElement p2 = elems.getPackageElement("p2"); + System.err.println("closing file manager"); + fm.close(); + TypeElement p2C2 = elems.getTypeElement("p2.C2"); + System.err.println("p2: " + p2 + "; p2C2: " + p2C2); + if (p2C2 != null) { + throw new Exception("p1.C1 found unexpectedly"); + } + } catch (ClosedFileSystemException e) { + throw new Exception("unexpected exception thrown", e); + } + + } + + private Path createJar(ToolBox tb) throws IOException { + Path jarSrc = Paths.get("jarSrc"); + Path jarClasses = Paths.get("jarClasses"); + Path jar = Paths.get("jar.jar"); + Files.createDirectories(jarClasses); + + tb.writeJavaFiles(jarSrc, + "package p1; public class C1 { }", + "package p2; public class C2 { }"); + + new JavacTask(tb) + .outdir(jarClasses) + .files(tb.findJavaFiles(jarSrc)) + .run() + .writeAll(); + new JarTask(tb) + .run("cf", jar.toString(), "-C", jarClasses.toString(), "p1", "p2"); + + return jar; + } +} + diff --git a/langtools/test/tools/javadoc/8147801/T8147801.java b/langtools/test/tools/javadoc/8147801/T8147801.java index 8e31f55dbff..9ff3072d105 100644 --- a/langtools/test/tools/javadoc/8147801/T8147801.java +++ b/langtools/test/tools/javadoc/8147801/T8147801.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -32,6 +32,8 @@ */ import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; import java.nio.file.ClosedFileSystemException; import java.nio.file.Files; import java.nio.file.Path; @@ -80,19 +82,22 @@ public class T8147801 { void test(boolean withOption) { System.err.println("Testing " + (withOption ? "with" : "without") + " option"); try { + String dump = ""; RootDoc root = getRootDoc(withOption); for (ClassDoc cd: root.specifiedClasses()) { - dump("", cd); + dump += dump(cd); } - if (!withOption) { - error("expected option did not occur"); + if (dump.contains("lib.Lib2.i")) { + if (!withOption) { + error("control case failed: Lib2 class file was read, unexpectedly, without using option"); + } + } else { + if (withOption) { + error("test case failed: could not read Lib2 class file, using option"); + } } } catch (ClosedFileSystemException e) { - if (withOption) { - error("Unexpected exception: " + e); - } else { - System.err.println("Exception received as expected: " + e); - } + error("Unexpected exception: " + e); } System.err.println(); } @@ -118,12 +123,21 @@ public class T8147801 { return cachedRoot; } - void dump(String prefix, ClassDoc cd) { - System.err.println(prefix + "class: " + cd); + String dump(ClassDoc cd) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + dump(pw, "", cd); + String out = sw.toString(); + System.err.println(out); + return out; + } + + void dump(PrintWriter out, String prefix, ClassDoc cd) { + out.println(prefix + "class: " + cd); for (FieldDoc fd: cd.fields()) { - System.err.println(fd); + out.println(prefix + " " + fd); if (fd.type().asClassDoc() != null) { - dump(prefix + " ", fd.type().asClassDoc()); + dump(out, prefix + " ", fd.type().asClassDoc()); } } } diff --git a/langtools/test/tools/javadoc/8147801/jarsrc/lib/Lib2.java b/langtools/test/tools/javadoc/8147801/jarsrc/lib/Lib2.java index 870103fa75e..41411b550d6 100644 --- a/langtools/test/tools/javadoc/8147801/jarsrc/lib/Lib2.java +++ b/langtools/test/tools/javadoc/8147801/jarsrc/lib/Lib2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -24,5 +24,5 @@ package lib; public class Lib2 { - int i; + public int i; } From ec3981561d477090ae28f0e9d459a6780cce5883 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 20 Jan 2017 09:26:49 +0100 Subject: [PATCH 12/16] 8171098: NPE when --add-modules java.corba is used Block annotations queue until enter is done, to avoid flushing annotations during module resolution. Reviewed-by: jjg --- .../com/sun/tools/javac/comp/Annotate.java | 10 ++++ .../sun/tools/javac/main/JavaCompiler.java | 13 +++-- .../JavacProcessingEnvironment.java | 6 +- .../sun/tools/javadoc/main/JavadocEnter.java | 6 +- .../sun/tools/javadoc/main/JavadocTool.java | 3 +- .../javadoc/internal/tool/JavadocEnter.java | 6 +- .../javadoc/internal/tool/JavadocTool.java | 3 +- .../javac/lib/combo/ReusableContext.java | 4 +- .../test/tools/javac/modules/EdgeCases.java | 58 ++++++++++++++++++- 9 files changed, 95 insertions(+), 14 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java index 72c832f9a36..9fe870af7a1 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -118,6 +118,8 @@ public class Annotate { Source source = Source.instance(context); allowRepeatedAnnos = source.allowRepeatedAnnotations(); sourceName = source.name; + + blockCount = 1; } /** Semaphore to delay annotation processing */ @@ -144,6 +146,10 @@ public class Annotate { /** are we blocking annotation processing? */ public boolean annotationsBlocked() {return blockCount > 0; } + public void enterDone() { + unblockAnnotations(); + } + public List fromAnnotations(List annotations) { if (annotations.isEmpty()) { return List.nil(); @@ -1316,4 +1322,8 @@ public class Annotate { } }; } + + public void newRound() { + blockCount = 1; + } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 9bfbbfdd571..64b02eaa438 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -363,7 +363,7 @@ public class JavaCompiler { **/ protected boolean implicitSourceFilesRead; - protected boolean enterDone; + private boolean enterDone; protected CompileStates compileStates; @@ -1042,7 +1042,7 @@ public class JavaCompiler { public List initModules(List roots) { modules.initModules(roots); if (roots.isEmpty()) { - enterDone = true; + enterDone(); } return roots; } @@ -1063,7 +1063,7 @@ public class JavaCompiler { enter.main(roots); - enterDone = true; + enterDone(); if (!taskListener.isEmpty()) { for (JCCompilationUnit unit: roots) { @@ -1725,6 +1725,11 @@ public class JavaCompiler { } } + public void enterDone() { + enterDone = true; + annotate.enterDone(); + } + public boolean isEnterDone() { return enterDone; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index e3321892fbe..06da0627b16 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -92,6 +92,7 @@ import com.sun.tools.javac.util.Options; import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; import static com.sun.tools.javac.code.Kinds.Kind.*; +import com.sun.tools.javac.comp.Annotate; import static com.sun.tools.javac.comp.CompileStates.CompileState; import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; @@ -123,6 +124,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea private final JavaCompiler compiler; private final Modules modules; private final Types types; + private final Annotate annotate; /** * Holds relevant state history of which processors have been @@ -219,6 +221,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea typeUtils = JavacTypes.instance(context); modules = Modules.instance(context); types = Types.instance(context); + annotate = Annotate.instance(context); processorOptions = initProcessorOptions(); unmatchedProcessorOptions = initUnmatchedProcessorOptions(); messages = JavacMessages.instance(context); @@ -1256,6 +1259,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea compiler.newRound(); modules.newRound(); types.newRound(); + annotate.newRound(); boolean foundError = false; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java index 1456b981186..6e745420be9 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -36,6 +36,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; import static com.sun.tools.javac.code.Kinds.Kind.*; +import com.sun.tools.javac.main.JavaCompiler; /** * Javadoc's own enter phase does a few things above and beyond that @@ -65,16 +66,19 @@ public class JavadocEnter extends Enter { super(context); messager = Messager.instance0(context); docenv = DocEnv.instance(context); + compiler = JavaCompiler.instance(context); } final Messager messager; final DocEnv docenv; + final JavaCompiler compiler; @Override public void main(List trees) { // count all Enter errors as warnings. int nerrors = messager.nerrors; super.main(trees); + compiler.enterDone(); messager.nwarnings += (messager.nerrors - nerrors); messager.nerrors = nerrors; } diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java index ccf911a3c53..41ee2c4a577 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -219,7 +219,6 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { // Enter symbols for all files docenv.notice("main.Building_tree"); javadocEnter.main(classTrees.toList().appendList(packageTrees.toList())); - enterDone = true; } catch (Abort ex) {} if (messager.nerrors() != 0) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocEnter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocEnter.java index 53023a6d52b..1af4c21a318 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocEnter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -36,6 +36,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; import static com.sun.tools.javac.code.Kinds.Kind.*; +import com.sun.tools.javac.main.JavaCompiler; /** * Javadoc's own enter phase does a few things above and beyond that @@ -64,16 +65,19 @@ public class JavadocEnter extends Enter { super(context); messager = Messager.instance0(context); toolEnv = ToolEnvironment.instance(context); + compiler = JavaCompiler.instance(context); } final Messager messager; final ToolEnvironment toolEnv; + final JavaCompiler compiler; @Override public void main(List trees) { // count all Enter errors as warnings. int nerrors = messager.nerrors; super.main(trees); + compiler.enterDone(); messager.nwarnings += (messager.nerrors - nerrors); messager.nerrors = nerrors; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java index bee71775e43..89693ae7b27 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -202,7 +202,6 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { javadocEnter.main(classTrees.toList().appendList(packageTrees)); etable.setClassDeclList(listClasses(classTrees.toList())); - enterDone = true; etable.analyze(); } catch (CompletionFailure cf) { throw new ToolException(ABNORMAL, cf.getMessage(), cf); diff --git a/langtools/test/tools/javac/lib/combo/ReusableContext.java b/langtools/test/tools/javac/lib/combo/ReusableContext.java index 7550c760265..a6c6b0c4a46 100644 --- a/langtools/test/tools/javac/lib/combo/ReusableContext.java +++ b/langtools/test/tools/javac/lib/combo/ReusableContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -38,6 +38,7 @@ import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ClassType; import com.sun.tools.javac.code.TypeTag; import com.sun.tools.javac.code.Types; +import com.sun.tools.javac.comp.Annotate; import com.sun.tools.javac.comp.Check; import com.sun.tools.javac.comp.CompileStates; import com.sun.tools.javac.comp.Enter; @@ -95,6 +96,7 @@ class ReusableContext extends Context implements TaskListener { Types.instance(this).newRound(); Check.instance(this).newRound(); Modules.instance(this).newRound(); + Annotate.instance(this).newRound(); CompileStates.instance(this).clear(); MultiTaskListener.instance(this).clear(); diff --git a/langtools/test/tools/javac/modules/EdgeCases.java b/langtools/test/tools/javac/modules/EdgeCases.java index 7c1dd6f1142..8585d57b7fb 100644 --- a/langtools/test/tools/javac/modules/EdgeCases.java +++ b/langtools/test/tools/javac/modules/EdgeCases.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8154283 8167320 + * @bug 8154283 8167320 8171098 * @summary tests for multi-module mode compilation * @library /tools/lib * @modules @@ -484,4 +484,58 @@ public class EdgeCases extends ModuleTestBase { throw new AssertionError("Unexpected output: " + log); } } + + @Test + public void testOnDemandCompletionModuleInfoJava(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1x"); + tb.writeJavaFiles(src_m1, + "@Deprecated module m1x { }"); + Path src_m2 = src.resolve("m2x"); + tb.writeJavaFiles(src_m2, + "module m2x { requires m1x; }"); + Path src_m3 = src.resolve("m3x"); + tb.writeJavaFiles(src_m3, + "module m3x { requires m2x; requires m1x; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + List log; + List expected; + + log = new JavacTask(tb) + .options("--module-source-path", src.toString()) + .outdir(classes) + .files(findJavaFiles(src_m1)) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expected = Arrays.asList(""); + + if (!expected.equals(log)) { + throw new IllegalStateException(log.toString()); + } + + log = new JavacTask(tb) + .options("--module-source-path", src.toString(), + "-XDrawDiagnostics", + "-Xlint:deprecation") + .outdir(classes) + .files(findJavaFiles(src_m3)) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expected = Arrays.asList( + "module-info.java:1:23: compiler.warn.has.been.deprecated.module: m1x", + "module-info.java:1:37: compiler.warn.has.been.deprecated.module: m1x", + "2 warnings" + ); + + if (!expected.equals(log)) { + throw new IllegalStateException(log.toString()); + } + } + } From b6e7bcbc6abbfd1bdf478b6b3f2f3a625832f510 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 20 Jan 2017 13:20:42 +0100 Subject: [PATCH 13/16] 8171177: Compiler should issue a warning for incubating modules that are resolved Javac needs to follow ModuleResolution.DO_NOT_RESOLVE_BY_DEFAULT and ModuleResolution.WARN_INCUBATING Reviewed-by: jjg --- .../com/sun/tools/javac/code/Symbol.java | 4 +- .../com/sun/tools/javac/comp/Modules.java | 29 +- .../tools/javac/resources/compiler.properties | 4 + .../classfile/ModuleResolution_attribute.java | 4 +- .../tools/javac/diags/examples.not-yet.txt | 1 + .../tools/javac/modules/IncubatingTest.java | 291 ++++++++++++++++++ .../model/testgetallmembers/Main.java | 4 +- 7 files changed, 325 insertions(+), 12 deletions(-) create mode 100644 langtools/test/tools/javac/modules/IncubatingTest.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index 39d2316f0fc..66fe857778a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -1045,7 +1045,7 @@ public abstract class Symbol extends AnnoConstruct implements Element { DO_NOT_RESOLVE_BY_DEFAULT(0x0001), WARN_DEPRECATED(0x0002), WARN_DEPRECATED_REMOVAL(0x0004), - WARN_INCUBATOR(0x0008); + WARN_INCUBATING(0x0008); public static int value(Set s) { int v = 0; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java index 4e3eaa82d9b..46b8ff40f89 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java @@ -41,6 +41,7 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.stream.Stream; import javax.lang.model.SourceVersion; @@ -114,6 +115,7 @@ import static com.sun.tools.javac.code.Flags.UNATTRIBUTED; import static com.sun.tools.javac.code.Kinds.Kind.ERR; import static com.sun.tools.javac.code.Kinds.Kind.MDL; import static com.sun.tools.javac.code.Kinds.Kind.MTH; +import com.sun.tools.javac.code.Symbol.ModuleResolutionFlags; import static com.sun.tools.javac.code.TypeTag.CLASS; /** @@ -1090,6 +1092,10 @@ public class Modules extends JCTree.Visitor { Predicate observablePred = sym -> (observable == null) ? (moduleFinder.findModule(sym).kind != ERR) : observable.contains(sym); Predicate systemModulePred = sym -> (sym.flags() & Flags.SYSTEM_MODULE) != 0; + Predicate noIncubatorPred = sym -> { + sym.complete(); + return !sym.resolutionFlags.contains(ModuleResolutionFlags.DO_NOT_RESOLVE_BY_DEFAULT); + }; Set enabledRoot = new LinkedHashSet<>(); if (rootModules.contains(syms.unnamedModule)) { @@ -1108,7 +1114,7 @@ public class Modules extends JCTree.Visitor { } for (ModuleSymbol sym : new HashSet<>(syms.getAllModules())) { - if (systemModulePred.test(sym) && observablePred.test(sym) && jdkModulePred.test(sym)) { + if (systemModulePred.test(sym) && observablePred.test(sym) && jdkModulePred.test(sym) && noIncubatorPred.test(sym)) { enabledRoot.add(sym); } } @@ -1128,14 +1134,14 @@ public class Modules extends JCTree.Visitor { Stream modules; switch (added) { case ALL_SYSTEM: - modules = syms.getAllModules() - .stream() - .filter(systemModulePred.and(observablePred)); + modules = new HashSet<>(syms.getAllModules()) + .stream() + .filter(systemModulePred.and(observablePred).and(noIncubatorPred)); break; case ALL_MODULE_PATH: - modules = syms.getAllModules() - .stream() - .filter(systemModulePred.negate().and(observablePred)); + modules = new HashSet<>(syms.getAllModules()) + .stream() + .filter(systemModulePred.negate().and(observablePred)); break; default: if (!isValidName(added)) @@ -1155,6 +1161,15 @@ public class Modules extends JCTree.Visitor { result.add(syms.unnamedModule); + String incubatingModules = result.stream() + .filter(msym -> msym.resolutionFlags.contains(ModuleResolutionFlags.WARN_INCUBATING)) + .map(msym -> msym.name.toString()) + .collect(Collectors.joining(",")); + + if (!incubatingModules.isEmpty()) { + log.warning(Warnings.IncubatingModules(incubatingModules)); + } + allModules = result; //add module versions from options, if any: diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 189a398d3ec..2310d26281f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1535,6 +1535,10 @@ compiler.warn.finally.cannot.complete=\ compiler.warn.poor.choice.for.module.name=\ module name {0} should avoid terminal digits +# 0: string +compiler.warn.incubating.modules=\ + using incubating module(s): {0} + # 0: symbol, 1: symbol compiler.warn.has.been.deprecated=\ {0} in {1} has been deprecated diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleResolution_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleResolution_attribute.java index d912931a406..e1ba78a3376 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleResolution_attribute.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleResolution_attribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -50,7 +50,7 @@ public class ModuleResolution_attribute extends Attribute { public ModuleResolution_attribute(ConstantPool constant_pool, int resolution_flags) throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.ModulePackages), + this(constant_pool.getUTF8Index(Attribute.ModuleResolution), resolution_flags); } diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index 367c4aec9e0..5f88b42c880 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -103,6 +103,7 @@ compiler.warn.annotation.method.not.found.reason # ClassReader compiler.warn.big.major.version # ClassReader compiler.warn.future.attr # ClassReader compiler.warn.illegal.char.for.encoding +compiler.warn.incubating.modules # requires adjusted classfile compiler.warn.invalid.archive.file compiler.warn.override.bridge compiler.warn.position.overflow # CRTable: caused by files with long lines >= 1024 chars diff --git a/langtools/test/tools/javac/modules/IncubatingTest.java b/langtools/test/tools/javac/modules/IncubatingTest.java new file mode 100644 index 00000000000..a839237c4e1 --- /dev/null +++ b/langtools/test/tools/javac/modules/IncubatingTest.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2015, 2017, 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 + * @bug 8171177 + * @summary Verify that ModuleResolution attribute flags are honored. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jdeps/com.sun.tools.classfile + * jdk.jdeps/com.sun.tools.javap + * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavapTask ModuleTestBase + * @run main IncubatingTest + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.Attributes; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ClassWriter; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; +import com.sun.tools.classfile.ConstantPool.CPInfo; +import com.sun.tools.classfile.ModuleResolution_attribute; +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.Task.Expect; + +public class IncubatingTest extends ModuleTestBase { + + public static void main(String... args) throws Exception { + new IncubatingTest().runTests(); + } + + @Test + public void testDoNotResolve(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, + "module jdk.i { exports api; }", + "package api; public class Api { }"); + Path classes = base.resolve("classes"); + Files.deleteIfExists(classes); + Path iClasses = classes.resolve("jdk.i"); + tb.createDirectories(iClasses); + + new JavacTask(tb) + .outdir(iClasses) + .files(findJavaFiles(src)) + .run() + .writeAll(); + + copyJavaBase(classes); + + Path jdkIModuleInfo = iClasses.resolve("module-info.class"); + addModuleResolutionAttribute(jdkIModuleInfo, ModuleResolution_attribute.DO_NOT_RESOLVE_BY_DEFAULT); + + Path testSrc = base.resolve("test-src"); + tb.writeJavaFiles(testSrc, + "class T { api.Api api; }"); + Path testClasses = base.resolve("test-classes"); + tb.createDirectories(testClasses); + + List log; + List expected; + + log = new JavacTask(tb) + .options("--system", "none", + "--upgrade-module-path", classes.toString(), + "-XDrawDiagnostics") + .outdir(testClasses) + .files(findJavaFiles(testSrc)) + .run(Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expected = Arrays.asList( + "T.java:1:11: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.does.not.read.from.unnamed: api, jdk.i)", + "1 error" + ); + + if (!expected.equals(log)) { + throw new AssertionError("Unexpected output: " + log); + } + + log = new JavacTask(tb) + .options("--system", "none", + "--upgrade-module-path", classes.toString(), + "--add-modules", "ALL-SYSTEM", + "-XDrawDiagnostics") + .outdir(testClasses) + .files(findJavaFiles(testSrc)) + .run(Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expected = Arrays.asList( + "T.java:1:11: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.does.not.read.from.unnamed: api, jdk.i)", + "1 error" + ); + + if (!expected.equals(log)) { + throw new AssertionError("Unexpected output: " + log); + } + + new JavacTask(tb) + .options("--system", "none", + "--upgrade-module-path", classes.toString(), + "--add-modules", "jdk.i") + .outdir(testClasses) + .files(findJavaFiles(testSrc)) + .run() + .writeAll(); + + Path testModuleSrc = base.resolve("test-module-src"); + tb.writeJavaFiles(testModuleSrc, + "module test { requires jdk.i; }", //explicit requires of an incubating module + "class T { api.Api api; }"); + Path testModuleClasses = base.resolve("test-module-classes"); + tb.createDirectories(testModuleClasses); + + new JavacTask(tb) + .options("--system", "none", + "--upgrade-module-path", classes.toString()) + .outdir(testModuleClasses) + .files(findJavaFiles(testModuleSrc)) + .run() + .writeAll(); + } + + @Test + public void testIncubating(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, + "module jdk.i { exports api; }", + "package api; public class Api { }"); + Path classes = base.resolve("classes"); + Files.deleteIfExists(classes); + Path iClasses = classes.resolve("jdk.i"); + tb.createDirectories(iClasses); + + new JavacTask(tb) + .outdir(iClasses) + .files(findJavaFiles(src)) + .run() + .writeAll(); + + Path jdkIModuleInfo = iClasses.resolve("module-info.class"); + addModuleResolutionAttribute(jdkIModuleInfo, ModuleResolution_attribute.WARN_INCUBATING); + + Path testSrc = base.resolve("test-src"); + tb.writeJavaFiles(testSrc, + "class T { api.Api api; }"); + Path testClasses = base.resolve("test-classes"); + tb.createDirectories(testClasses); + + List log; + List expected; + + log = new JavacTask(tb) + .options("--module-path", classes.toString(), + "--add-modules", "jdk.i", + "-XDrawDiagnostics", + "-Werror") + .outdir(testClasses) + .files(findJavaFiles(testSrc)) + .run(Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expected = Arrays.asList( + "- compiler.warn.incubating.modules: jdk.i", + "- compiler.err.warnings.and.werror", + "1 error", + "1 warning" + ); + + if (!expected.equals(log)) { + throw new AssertionError("Unexpected output: " + log); + } + + Path testModuleSrc = base.resolve("test-module-src"); + tb.writeJavaFiles(testModuleSrc, + "module test { requires jdk.i; }", //explicit requires of an incubating module + "class T { api.Api api; }"); + Path testModuleClasses = base.resolve("test-module-classes"); + tb.createDirectories(testModuleClasses); + + log = new JavacTask(tb) + .options("--module-path", classes.toString(), + "-XDrawDiagnostics", + "-Werror") + .outdir(testModuleClasses) + .files(findJavaFiles(testModuleSrc)) + .run(Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expected = Arrays.asList( + "- compiler.warn.incubating.modules: jdk.i", + "- compiler.err.warnings.and.werror", + "1 error", + "1 warning" + ); + + if (!expected.equals(log)) { + throw new AssertionError("Unexpected output: " + log); + } + } + + private void copyJavaBase(Path targetDir) throws IOException { + FileSystem jrt = FileSystems.getFileSystem(URI.create("jrt:/")); + Path javaBase = jrt.getPath("modules", "java.base"); + + if (!Files.exists(javaBase)) { + throw new AssertionError("No java.base?"); + } + + Path javaBaseClasses = targetDir.resolve("java.base"); + + for (Path clazz : tb.findFiles("class", javaBase)) { + Path target = javaBaseClasses.resolve(javaBase.relativize(clazz).toString()); + Files.createDirectories(target.getParent()); + Files.copy(clazz, target); + } + } + + private void addModuleResolutionAttribute(Path classfile, int resolution_flags) throws Exception { + ClassFile cf = ClassFile.read(classfile); + Attributes attrs = cf.attributes; + List cpData = new ArrayList<>(); + cpData.add(null); + for (CPInfo info : cf.constant_pool.entries()) { + cpData.add(info); + if (info.size() == 2) + cpData.add(null); + } + cpData.add(new CONSTANT_Utf8_info(Attribute.ModuleResolution)); + ConstantPool newCP = new ConstantPool(cpData.toArray(new CPInfo[0])); + ModuleResolution_attribute res = new ModuleResolution_attribute(newCP, resolution_flags); + Map newAttributeMap = new HashMap<>(attrs.map); + newAttributeMap.put(Attribute.ModuleResolution, res); + Attributes newAttrs = new Attributes(newAttributeMap); + ClassFile newCF = new ClassFile(cf.magic, + cf.minor_version, + cf.major_version, + newCP, + cf.access_flags, + cf.this_class, + cf.super_class, + cf.interfaces, + cf.fields, + cf.methods, + newAttrs); + try (OutputStream out = Files.newOutputStream(classfile)) { + new ClassWriter().write(newCF, out); + } + } +} diff --git a/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java b/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java index 6bc313d653d..0e2a6929b22 100644 --- a/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java +++ b/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2017, 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 @@ -88,6 +88,8 @@ public class Main { Path path = fm.asPath(file); int moduleIndex = path.getNameCount() - type.split("\\Q.\\E").length - 1; String moduleName = path.getName(moduleIndex).toString(); + if (moduleName.startsWith("jdk.incubator.")) //incubator modules not in module graph by default + continue; try { ModuleElement me = elements.getModuleElement(moduleName); me.getClass(); From 3e7e4c275b5dc2f6b2fef353002af7131d28a1a5 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 20 Jan 2017 15:32:03 +0100 Subject: [PATCH 14/16] 8172809: Error compiling javafx modules after fix for JDK-8169197 Properly stripping broken requires from ModuleSymbols. Reviewed-by: jjg, mcimadamore --- .../com/sun/tools/javac/comp/Modules.java | 11 +-- .../test/tools/javac/modules/EdgeCases.java | 91 ++++++++++++++++++- 2 files changed, 92 insertions(+), 10 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java index 46b8ff40f89..a60ca6ceb92 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java @@ -978,7 +978,7 @@ public class Modules extends JCTree.Visitor { @Override public void visitRequires(JCRequires tree) { - if (tree.directive != null) { + if (tree.directive != null && allModules().contains(tree.directive.module)) { chk.checkDeprecated(tree.moduleName.pos(), msym, tree.directive.module); msym.directives = msym.directives.prepend(tree.directive); } @@ -1263,7 +1263,6 @@ public class Modules extends JCTree.Visitor { msym.requires = msym.requires.appendList(List.from(addReads.getOrDefault(msym, Collections.emptySet()))); List requires = msym.requires; - List previous = null; while (requires.nonEmpty()) { if (!allModules().contains(requires.head.module)) { @@ -1278,13 +1277,7 @@ public class Modules extends JCTree.Visitor { } else { Assert.check((msym.flags() & Flags.AUTOMATIC_MODULE) == 0); } - if (previous != null) { - previous.tail = requires.tail; - } else { - msym.requires.tail = requires.tail; - } - } else { - previous = requires; + msym.requires = List.filter(msym.requires, requires.head); } requires = requires.tail; } diff --git a/langtools/test/tools/javac/modules/EdgeCases.java b/langtools/test/tools/javac/modules/EdgeCases.java index 8585d57b7fb..8192eb18285 100644 --- a/langtools/test/tools/javac/modules/EdgeCases.java +++ b/langtools/test/tools/javac/modules/EdgeCases.java @@ -23,13 +23,14 @@ /* * @test - * @bug 8154283 8167320 8171098 + * @bug 8154283 8167320 8171098 8172809 * @summary tests for multi-module mode compilation * @library /tools/lib * @modules * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.code * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.util * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase * @run main EdgeCases */ @@ -44,7 +45,16 @@ import java.util.List; import java.util.Objects; import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedOptions; +import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; +import javax.lang.model.element.ModuleElement; +import javax.lang.model.element.ModuleElement.RequiresDirective; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.ElementFilter; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; @@ -485,6 +495,85 @@ public class EdgeCases extends ModuleTestBase { } } + @Test + public void testStripUnknownRequired(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1x"); + tb.writeJavaFiles(src_m1, + "module m1x { }"); + Path src_m2 = src.resolve("m2x"); + tb.writeJavaFiles(src_m2, + "module m2x { }"); + Path src_m3 = src.resolve("m3x"); + tb.writeJavaFiles(src_m3, + "module m3x { }"); + Path src_m4 = src.resolve("m4x"); + tb.writeJavaFiles(src_m4, + "module m4x { }"); + Path src_test = src.resolve("test"); + tb.writeJavaFiles(src_test, + "module test { requires m1x; requires m2x; requires java.base; requires m3x; requires m4x; }"); + Path src_compile = src.resolve("compile"); + tb.writeJavaFiles(src_compile, + "module compile { exports p to test; }", + "package p; public class Test { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + List log = new JavacTask(tb) + .options("-processor", ListRequires.class.getName(), + "--module-source-path", src.toString(), + "--limit-modules", "compile", + "-XDaccessInternalAPI=true") + .outdir(classes) + .files(findJavaFiles(src_compile)) + .run(Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.STDOUT); + + List expected = Arrays.asList( + "from directives:", + "java.base", + "from requires:", + "java.base" + ); + if (!Objects.equals(log, expected)) + throw new AssertionError("Unexpected output: " + log); + } + + @SupportedAnnotationTypes("*") + @SupportedOptions("expectedEnclosedElements") + public static final class ListRequires extends AbstractProcessor { + + private int round; + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (round++ == 0) { + ModuleElement compileE = processingEnv.getElementUtils().getModuleElement("compile"); + ModuleElement testE = ElementFilter.exportsIn(compileE.getDirectives()).get(0).getTargetModules().get(0); + + System.out.println("from directives:"); + for (RequiresDirective rd : ElementFilter.requiresIn(testE.getDirectives())) { + System.out.println(rd.getDependency().getSimpleName()); + } + + System.out.println("from requires:"); + for (RequiresDirective rd : ((ModuleSymbol) testE).requires) { + System.out.println(rd.getDependency().getSimpleName()); + } + } + + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + } + @Test public void testOnDemandCompletionModuleInfoJava(Path base) throws Exception { Path src = base.resolve("src"); From 721001933ddcaed0df9f9d85181ac8a196145a5e Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 20 Jan 2017 15:32:07 +0100 Subject: [PATCH 15/16] 8173117: Compilation significantly slower after JDK-8169197 Only using recovery search when an error is inevitable. Reviewed-by: jjg, mcimadamore --- .../com/sun/tools/javac/code/Symtab.java | 10 +- .../com/sun/tools/javac/comp/Resolve.java | 150 +++++++++++------- .../sun/tools/javac/model/JavacElements.java | 49 +++--- .../com/sun/tools/javac/util/Convert.java | 14 +- .../modules/ConvenientAccessErrorsTest.java | 119 +++++++++++++- .../test/tools/javac/modules/EdgeCases.java | 29 +++- .../javac/modules/PackageMultipleModules.java | 9 +- 7 files changed, 285 insertions(+), 95 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java index f3fdb5d3486..493bad557a6 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -818,4 +818,12 @@ public class Symtab { public Collection getAllModules() { return modules.values(); } + + public Iterable getClassesForName(Name candidate) { + return classes.getOrDefault(candidate, Collections.emptyMap()).values(); + } + + public Iterable getPackagesForName(Name candidate) { + return packages.getOrDefault(candidate, Collections.emptyMap()).values(); + } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index dfb28eca2cd..3b1743d2ff4 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -41,6 +41,7 @@ import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template; import com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind; import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.main.Option; +import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; @@ -61,12 +62,12 @@ import java.util.Map; import java.util.Set; import java.util.function.BiFunction; import java.util.function.BiPredicate; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; import javax.lang.model.element.ElementVisitor; -import com.sun.tools.javac.code.Directive.ExportsDirective; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Flags.BLOCK; import static com.sun.tools.javac.code.Flags.STATIC; @@ -74,9 +75,8 @@ import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; -import com.sun.tools.javac.resources.CompilerProperties.Errors; -import com.sun.tools.javac.resources.CompilerProperties.Fragments; import static com.sun.tools.javac.tree.JCTree.Tag.*; +import static com.sun.tools.javac.util.Iterators.createCompoundIterator; /** Helper class for name resolution, used mostly by the attribution phase. * @@ -1970,7 +1970,7 @@ public class Resolve { * @param env The current environment. * @param name The fully qualified name of the class to be loaded. */ - Symbol loadClass(Env env, Name name) { + Symbol loadClass(Env env, Name name, RecoveryLoadClass recoveryLoadClass) { try { ClassSymbol c = finder.loadClass(env.toplevel.modle, name); return isAccessible(env, c) ? c : new AccessError(env, null, c); @@ -1987,40 +1987,60 @@ public class Resolve { } } - public static interface RecoveryLoadClass { + public interface RecoveryLoadClass { Symbol loadClass(Env env, Name name); } - private RecoveryLoadClass recoveryLoadClass = new RecoveryLoadClass() { - @Override - public Symbol loadClass(Env env, Name name) { - if (allowModules) { - Scope importScope = env.toplevel.namedImportScope; - Symbol existing = importScope.findFirst(Convert.shortName(name), - sym -> sym.kind == TYP && sym.flatName() == name); + private final RecoveryLoadClass noRecovery = (env, name) -> null; - if (existing != null) { - return new InvisibleSymbolError(env, true, existing); - } - - return lookupInvisibleSymbol(env, name, syms::getClass, (ms, n) -> { + private final RecoveryLoadClass doRecoveryLoadClass = new RecoveryLoadClass() { + @Override public Symbol loadClass(Env env, Name name) { + List candidates = Convert.classCandidates(name); + return lookupInvisibleSymbol(env, name, + n -> () -> createCompoundIterator(candidates, + c -> syms.getClassesForName(c) + .iterator()), + (ms, n) -> { + for (Name candidate : candidates) { try { - return finder.loadClass(ms, n); + return finder.loadClass(ms, candidate); } catch (CompletionFailure cf) { //ignore - return null; } - }, sym -> sym.kind == Kind.TYP, false, typeNotFound); - } - return null; + } + return null; + }, sym -> sym.kind == Kind.TYP, false, typeNotFound); } }; - public RecoveryLoadClass setRecoveryLoadClass(RecoveryLoadClass recovery) { - RecoveryLoadClass prev = recoveryLoadClass; - recoveryLoadClass = recovery; - return prev; - } + private final RecoveryLoadClass namedImportScopeRecovery = (env, name) -> { + Scope importScope = env.toplevel.namedImportScope; + Symbol existing = importScope.findFirst(Convert.shortName(name), + sym -> sym.kind == TYP && sym.flatName() == name); + + if (existing != null) { + return new InvisibleSymbolError(env, true, existing); + } + return null; + }; + + private final RecoveryLoadClass starImportScopeRecovery = (env, name) -> { + Scope importScope = env.toplevel.starImportScope; + Symbol existing = importScope.findFirst(Convert.shortName(name), + sym -> sym.kind == TYP && sym.flatName() == name); + + if (existing != null) { + try { + existing = finder.loadClass(existing.packge().modle, name); + + return new InvisibleSymbolError(env, true, existing); + } catch (CompletionFailure cf) { + //ignore + } + } + + return null; + }; Symbol lookupPackage(Env env, Name name) { PackageSymbol pack = syms.lookupPackage(env.toplevel.modle, name); @@ -2034,7 +2054,7 @@ public class Resolve { .stream() .anyMatch(p -> p.fullname.startsWith(nameAndDot)); - return lookupInvisibleSymbol(env, name, syms::getPackage, syms::enterPackage, sym -> { + return lookupInvisibleSymbol(env, name, syms::getPackagesForName, syms::enterPackage, sym -> { sym.complete(); return sym.exists(); }, prefixOfKnown, pack); @@ -2059,42 +2079,44 @@ public class Resolve { return TreeInfo.fullName(((JCFieldAccess) qualid).selected) == name; } - private Symbol lookupInvisibleSymbol(Env env, - Name name, - BiFunction get, - BiFunction load, - Predicate validate, - boolean suppressError, - Symbol defaultResult) { + private Symbol lookupInvisibleSymbol(Env env, + Name name, + Function> get, + BiFunction load, + Predicate validate, + boolean suppressError, + Symbol defaultResult) { //even if a class/package cannot be found in the current module and among packages in modules //it depends on that are exported for any or this module, the class/package may exist internally //in some of these modules, or may exist in a module on which this module does not depend. //Provide better diagnostic in such cases by looking for the class in any module: + Iterable candidates = get.apply(name); + + for (S sym : candidates) { + if (validate.test(sym)) + return new InvisibleSymbolError(env, suppressError, sym); + } + Set recoverableModules = new HashSet<>(syms.getAllModules()); recoverableModules.remove(env.toplevel.modle); for (ModuleSymbol ms : recoverableModules) { - Symbol sym = get.apply(ms, name); - //avoid overly eager completing classes from source-based modules, as those //may not be completable with the current compiler settings: - if (sym == null && (ms.sourceLocation == null)) { + if (ms.sourceLocation == null) { if (ms.classLocation == null) { ms = moduleFinder.findModule(ms); } if (ms.kind != ERR) { - sym = load.apply(ms, name); + S sym = load.apply(ms, name); + + if (sym != null && validate.test(sym)) { + return new InvisibleSymbolError(env, suppressError, sym); + } } } - - if (sym == null) - continue; - - if (validate.test(sym)) { - return new InvisibleSymbolError(env, suppressError, sym); - } } return defaultResult; @@ -2186,10 +2208,10 @@ public class Resolve { * @param scope The scope in which to look for the type. * @param name The type's name. */ - Symbol findGlobalType(Env env, Scope scope, Name name) { + Symbol findGlobalType(Env env, Scope scope, Name name, RecoveryLoadClass recoveryLoadClass) { Symbol bestSoFar = typeNotFound; for (Symbol s : scope.getSymbolsByName(name)) { - Symbol sym = loadClass(env, s.flatName()); + Symbol sym = loadClass(env, s.flatName(), recoveryLoadClass); if (bestSoFar.kind == TYP && sym.kind == TYP && bestSoFar != sym) return new AmbiguityError(bestSoFar, sym); @@ -2260,15 +2282,15 @@ public class Resolve { } if (!env.tree.hasTag(IMPORT)) { - sym = findGlobalType(env, env.toplevel.namedImportScope, name); + sym = findGlobalType(env, env.toplevel.namedImportScope, name, namedImportScopeRecovery); if (sym.exists()) return sym; else bestSoFar = bestOf(bestSoFar, sym); - sym = findGlobalType(env, env.toplevel.packge.members(), name); + sym = findGlobalType(env, env.toplevel.packge.members(), name, noRecovery); if (sym.exists()) return sym; else bestSoFar = bestOf(bestSoFar, sym); - sym = findGlobalType(env, env.toplevel.starImportScope, name); + sym = findGlobalType(env, env.toplevel.starImportScope, name, starImportScopeRecovery); if (sym.exists()) return sym; else bestSoFar = bestOf(bestSoFar, sym); } @@ -2315,7 +2337,11 @@ public class Resolve { Name fullname = TypeSymbol.formFullName(name, pck); Symbol bestSoFar = typeNotFound; if (kind.contains(KindSelector.TYP)) { - Symbol sym = loadClass(env, fullname); + RecoveryLoadClass recoveryLoadClass = + allowModules && !kind.contains(KindSelector.PCK) && + !pck.exists() && !env.info.isSpeculative ? + doRecoveryLoadClass : noRecovery; + Symbol sym = loadClass(env, fullname, recoveryLoadClass); if (sym.exists()) { // don't allow programs to use flatnames if (name == sym.name) return sym; @@ -4136,11 +4162,21 @@ public class Resolve { JCDiagnostic details = inaccessiblePackageReason(env, sym.packge()); - if (pos.getTree() != null && pos.getTree().hasTag(SELECT) && sym.owner.kind == PCK) { - pos = ((JCFieldAccess) pos.getTree()).selected.pos(); + if (pos.getTree() != null) { + Symbol o = sym; + JCTree tree = pos.getTree(); - return diags.create(dkind, log.currentSource(), - pos, "package.not.visible", sym.packge(), details); + while (o.kind != PCK && tree.hasTag(SELECT)) { + o = o.owner; + tree = ((JCFieldAccess) tree).selected; + } + + if (o.kind == PCK) { + pos = tree.pos(); + + return diags.create(dkind, log.currentSource(), + pos, "package.not.visible", o, details); + } } return diags.create(dkind, log.currentSource(), diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java index 34cba3183d6..fdbd31d2971 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java @@ -184,39 +184,34 @@ public class JavacElements implements Elements { return nameToSymbol(syms.noModule, nameStr, clazz); } - RecoveryLoadClass prevRecoveryLoadClass = resolve.setRecoveryLoadClass((env, name) -> null); - try { - Set found = new LinkedHashSet<>(); + Set found = new LinkedHashSet<>(); - for (ModuleSymbol msym : modules.allModules()) { - S sym = nameToSymbol(msym, nameStr, clazz); + for (ModuleSymbol msym : modules.allModules()) { + S sym = nameToSymbol(msym, nameStr, clazz); - if (sym != null) { - if (!allowModules || clazz == ClassSymbol.class || !sym.members().isEmpty()) { - //do not add packages without members: - found.add(sym); - } + if (sym != null) { + if (!allowModules || clazz == ClassSymbol.class || !sym.members().isEmpty()) { + //do not add packages without members: + found.add(sym); } } + } - if (found.size() == 1) { - return found.iterator().next(); - } else if (found.size() > 1) { - //more than one element found, produce a note: - if (alreadyWarnedDuplicates.add(methodName + ":" + nameStr)) { - String moduleNames = found.stream() - .map(s -> s.packge().modle) - .map(m -> m.toString()) - .collect(Collectors.joining(", ")); - log.note(Notes.MultipleElements(methodName, nameStr, moduleNames)); - } - return null; - } else { - //not found, or more than one element found: - return null; + if (found.size() == 1) { + return found.iterator().next(); + } else if (found.size() > 1) { + //more than one element found, produce a note: + if (alreadyWarnedDuplicates.add(methodName + ":" + nameStr)) { + String moduleNames = found.stream() + .map(s -> s.packge().modle) + .map(m -> m.toString()) + .collect(Collectors.joining(", ")); + log.note(Notes.MultipleElements(methodName, nameStr, moduleNames)); } - } finally { - resolve.setRecoveryLoadClass(prevRecoveryLoadClass); + return null; + } else { + //not found, or more than one element found: + return null; } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Convert.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Convert.java index a29b3971f2f..98095066567 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Convert.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Convert.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -335,4 +335,16 @@ public class Convert { } return names; } + + public static List classCandidates(Name name) { + List names = List.nil(); + String nameStr = name.toString(); + int index = -1; + while ((index = nameStr.indexOf('.', index + 1)) > 0) { + String pack = nameStr.substring(0, index + 1); + String clz = nameStr.substring(index + 1).replace('.', '$'); + names = names.prepend(name.table.names.fromString(pack + clz)); + } + return names.reverse(); + } } diff --git a/langtools/test/tools/javac/modules/ConvenientAccessErrorsTest.java b/langtools/test/tools/javac/modules/ConvenientAccessErrorsTest.java index 66728a98b89..45c2d388a8b 100644 --- a/langtools/test/tools/javac/modules/ConvenientAccessErrorsTest.java +++ b/langtools/test/tools/javac/modules/ConvenientAccessErrorsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -23,11 +23,12 @@ /* * @test - * @bug 8169197 8172668 + * @bug 8169197 8172668 8173117 * @summary Check convenient errors are produced for inaccessible classes. * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.util * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase * @run main ConvenientAccessErrorsTest */ @@ -37,6 +38,10 @@ import java.nio.file.Path; import java.util.Arrays; import java.util.List; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Convert; +import com.sun.tools.javac.util.Name; +import com.sun.tools.javac.util.Names; import toolbox.JarTask; import toolbox.JavacTask; import toolbox.Task; @@ -78,6 +83,37 @@ public class ConvenientAccessErrorsTest extends ModuleTestBase { throw new Exception("expected output not found; actual: " + log); } + @Test + public void testNoDepNested(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1x"); + tb.writeJavaFiles(src_m1, + "module m1x { exports api; }", + "package api; public class Api { public static class Nested {} }"); + Path src_m2 = src.resolve("m2x"); + tb.writeJavaFiles(src_m2, + "module m2x { }", + "package test; public class Test { api.Api.Nested nested; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + List log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--module-source-path", src.toString()) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected = Arrays.asList( + "Test.java:1:35: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.does.not.read: m2x, api, m1x)", + "1 error"); + + if (!expected.equals(log)) + throw new Exception("expected output not found; actual: " + log); + } + @Test public void testNotExported(Path base) throws Exception { Path src = base.resolve("src"); @@ -390,8 +426,7 @@ public class ConvenientAccessErrorsTest extends ModuleTestBase { List expected = Arrays.asList( "Test.java:1:22: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.not.exported: api, m1x)", - "Test.java:1:49: compiler.err.not.def.access.package.cant.access: api.Api, api, (compiler.misc.not.def.access.not.exported: api, m1x)", - "2 errors"); + "1 error"); if (!expected.equals(log)) throw new Exception("expected output not found; actual: " + log); @@ -593,4 +628,80 @@ public class ConvenientAccessErrorsTest extends ModuleTestBase { throw new Exception("expected output not found; actual: " + log); } + @Test + public void testInaccessibleInSourceModuleViaBinaryModule(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1x"); + tb.writeJavaFiles(src_m1, + "@Deprecated module m1x { }"); + Path src_m2 = src.resolve("m2x"); + tb.writeJavaFiles(src_m2, + "module m2x { requires transitive m1x; }"); + Path src_m3 = src.resolve("m3x"); + tb.writeJavaFiles(src_m3, + "module m3x { requires transitive m2x; exports api; }", + "package api; class Api { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("-XDrawDiagnostics", + "--module-source-path", src.toString()) + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + + tb.cleanDirectory(classes.resolve("m2x")); //force completion from source if needed + Files.delete(classes.resolve("m2x")); + + tb.cleanDirectory(src_m3); //binary only module + Files.delete(src_m3); + + //m4x does not depend on m1x/m2x/m3x, so cannot access api.Api + //but the recovery search should not complete m2x, as that would cause a deprecation warning: + Path src_m4 = src.resolve("m4x"); + tb.writeJavaFiles(src_m4, + "module m4x { }", + "package m4x; public class Test extends api.Api { }"); + + List log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--module-source-path", src.toString(), + "--module-path", classes.toString(), + "-Xlint:deprecation") + .outdir(classes) + .files(findJavaFiles(src_m4)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected = Arrays.asList( + "Test.java:1:40: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.does.not.read: m4x, api, m3x)", + "1 error"); + + if (!expected.equals(log)) + throw new Exception("expected output not found; actual: " + log); + } + + @Test + public void testConvertNameCandidates(Path base) throws Exception { + Context ctx = new Context(); + Names names = Names.instance(ctx); + Name name = names.fromString("com.sun.tools.javac.Attr.BreakAttr"); + + com.sun.tools.javac.util.List actual = + Convert.classCandidates(name).map(n -> n.toString()); + List expected = Arrays.asList( + "com.sun$tools$javac$Attr$BreakAttr", + "com.sun.tools$javac$Attr$BreakAttr", + "com.sun.tools.javac$Attr$BreakAttr", + "com.sun.tools.javac.Attr$BreakAttr", + "com.sun.tools.javac.Attr.BreakAttr" + ); + + if (!expected.equals(actual)) { + throw new Exception("Expected names not generated: " + actual); + } + } } diff --git a/langtools/test/tools/javac/modules/EdgeCases.java b/langtools/test/tools/javac/modules/EdgeCases.java index 8192eb18285..a9bf4814228 100644 --- a/langtools/test/tools/javac/modules/EdgeCases.java +++ b/langtools/test/tools/javac/modules/EdgeCases.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8154283 8167320 8171098 8172809 + * @bug 8154283 8167320 8171098 8172809 8173117 * @summary tests for multi-module mode compilation * @library /tools/lib * @modules @@ -495,6 +495,33 @@ public class EdgeCases extends ModuleTestBase { } } + @Test + public void testInvisibleClassVisiblePackageClash(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1x"); + tb.writeJavaFiles(src_m1, + "module m1x { }", + "package m1x;\n" + + "import m1x.a.*; public class Test { A a; }\n", + "package m1x.a;\n" + + "public class A { }\n"); + Path src_m2 = src.resolve("m2x"); + tb.writeJavaFiles(src_m2, + "module m2x { }", + "package m1x;\n" + + "public class a { public static class A { } }\n"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "-XDrawDiagnostics") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + @Test public void testStripUnknownRequired(Path base) throws Exception { Path src = base.resolve("src"); diff --git a/langtools/test/tools/javac/modules/PackageMultipleModules.java b/langtools/test/tools/javac/modules/PackageMultipleModules.java index d96d0657832..fa3cfed5997 100644 --- a/langtools/test/tools/javac/modules/PackageMultipleModules.java +++ b/langtools/test/tools/javac/modules/PackageMultipleModules.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -70,9 +70,10 @@ public class PackageMultipleModules extends ModuleTestBase { .writeAll() .getOutputLines(Task.OutputKind.DIRECT); - List expected = Arrays.asList("A.java:1:22: compiler.err.package.not.visible: test, (compiler.misc.not.def.access.does.not.read: m1x, test, m2x)", - "B.java:1:22: compiler.err.package.not.visible: test, (compiler.misc.not.def.access.does.not.read: m2x, test, m1x)", - "2 errors"); + List expected = Arrays.asList( + "A.java:1:26: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.package, test, null)", + "B.java:1:26: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.package, test, null)", + "2 errors"); if (!log.equals(expected)) throw new Exception("expected output not found"); } From 6e24cb584cc5ae942fac8aa20644292f81db8850 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Fri, 20 Jan 2017 08:29:59 -0800 Subject: [PATCH 16/16] 8170692: inconsistent check of module-related options against target version Reviewed-by: jjg --- .../share/classes/com/sun/tools/javac/main/Arguments.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java index ba96d875153..179cd04f721 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java @@ -588,7 +588,9 @@ public class Arguments { checkOptionAllowed(t.compareTo(Target.JDK1_9) >= 0, option -> error("err.option.not.allowed.with.target", option.getPrimaryName(), t.name), Option.MODULE_SOURCE_PATH, Option.UPGRADE_MODULE_PATH, - Option.SYSTEM, Option.MODULE_PATH, Option.ADD_MODULES, Option.LIMIT_MODULES, + Option.SYSTEM, Option.MODULE_PATH, Option.ADD_MODULES, + Option.ADD_EXPORTS, Option.ADD_OPENS, Option.ADD_READS, + Option.LIMIT_MODULES, Option.PATCH_MODULE); if (fm.hasLocation(StandardLocation.MODULE_SOURCE_PATH)) {