ee3be0bb56
Reviewed-by: darcy
256 lines
8.9 KiB
Java
256 lines
8.9 KiB
Java
/*
|
|
* Copyright (c) 2022, 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 8280688
|
|
* @summary doclint reference checks withstand warning suppression
|
|
* @library /tools/lib ../../lib
|
|
* @modules jdk.compiler/com.sun.tools.javac.api
|
|
* jdk.compiler/com.sun.tools.javac.main
|
|
* jdk.javadoc/jdk.javadoc.internal.api
|
|
* jdk.javadoc/jdk.javadoc.internal.tool
|
|
* @build toolbox.JavacTask toolbox.JavadocTask toolbox.TestRunner toolbox.ToolBox
|
|
* @run main DocLintReferencesTest
|
|
*/
|
|
|
|
import toolbox.JavacTask;
|
|
import toolbox.JavadocTask;
|
|
import toolbox.Task;
|
|
import toolbox.TestRunner;
|
|
import toolbox.ToolBox;
|
|
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
|
|
/**
|
|
* Combo test for how javac and javadoc handle {@code @see MODULE/TYPE}
|
|
* for different combinations of MODULE and TYPE, with and without
|
|
* {@code @SuppressWarnings("doclint") }.
|
|
*
|
|
* Generally, in javac, references to unknown elements are reported
|
|
* as suppressible warnings if the module is not resolved in the module graph.
|
|
* Otherwise, in both javac and javadoc, any issues with references
|
|
* are reported as errors.
|
|
*
|
|
* This allows references to other modules to appear in documentation comments
|
|
* without causing a hard error if the modules are not available at compile-time.
|
|
*/
|
|
public class DocLintReferencesTest extends TestRunner {
|
|
|
|
public static void main(String... args) throws Exception {
|
|
DocLintReferencesTest t = new DocLintReferencesTest();
|
|
t.runTests();
|
|
}
|
|
|
|
DocLintReferencesTest() {
|
|
super(System.err);
|
|
}
|
|
|
|
private final ToolBox tb = new ToolBox();
|
|
|
|
enum SuppressKind { NO, YES }
|
|
enum ModuleKind { NONE, BAD, NOT_FOUND, GOOD }
|
|
enum TypeKind { NONE, BAD, NOT_FOUND, GOOD }
|
|
|
|
@Test
|
|
public void comboTest () {
|
|
for (SuppressKind sk : SuppressKind.values() ) {
|
|
for (ModuleKind mk : ModuleKind.values() ) {
|
|
for (TypeKind tk: TypeKind.values() ) {
|
|
if (mk == ModuleKind.NONE && tk == TypeKind.NONE) {
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
test(sk, mk, tk);
|
|
} catch (Throwable e) {
|
|
error("Exception " + e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void test(SuppressKind sk, ModuleKind mk, TypeKind tk) throws Exception {
|
|
out.println();
|
|
out.println("*** Test SuppressKind:" + sk + " ModuleKind: " + mk + " TypeKind: " + tk);
|
|
Path base = Path.of(sk + "-" + mk + "-" + tk);
|
|
|
|
String sw = switch (sk) {
|
|
case NO -> "";
|
|
case YES -> "@SuppressWarnings(\"doclint\")";
|
|
};
|
|
String m = switch (mk) {
|
|
case NONE -> "";
|
|
case BAD -> "bad-name/";
|
|
case NOT_FOUND -> "not.found/";
|
|
case GOOD -> "java.base/";
|
|
};
|
|
String t = switch (tk) {
|
|
case NONE -> "";
|
|
case BAD -> "bad-name";
|
|
case NOT_FOUND -> "java.lang.NotFound";
|
|
case GOOD -> "java.lang.Object";
|
|
};
|
|
|
|
Path src = base.resolve("src");
|
|
tb.writeJavaFiles(src, """
|
|
package p;
|
|
/**
|
|
* Comment.
|
|
* @see #M##T#
|
|
*/
|
|
#SW#
|
|
public class C {
|
|
private C() { }
|
|
}
|
|
"""
|
|
.replace("#M#", m)
|
|
.replace("#T#", t)
|
|
.replace("#SW#", sw));
|
|
|
|
testJavac(sk, mk, tk, base, src);
|
|
testJavadoc(sk, mk, tk, base, src);
|
|
}
|
|
|
|
void testJavac(SuppressKind sk, ModuleKind mk, TypeKind tk, Path base, Path src) throws Exception {
|
|
Files.createDirectories(base.resolve("classes"));
|
|
|
|
out.println("javac:");
|
|
try {
|
|
String s = predictOutput(sk, mk, tk, false);
|
|
Task.Expect e = s.isEmpty() ? Task.Expect.SUCCESS : Task.Expect.FAIL;
|
|
|
|
String o = new JavacTask(tb)
|
|
.outdir(base.resolve("classes"))
|
|
.options("-Xdoclint:all/protected", "-Werror")
|
|
.files(tb.findJavaFiles(src))
|
|
.run(e)
|
|
.writeAll()
|
|
.getOutput(Task.OutputKind.DIRECT);
|
|
|
|
checkOutput(s, o);
|
|
|
|
} catch (Throwable t) {
|
|
error("Error: " + t);
|
|
}
|
|
out.println();
|
|
}
|
|
|
|
void testJavadoc(SuppressKind sk, ModuleKind mk, TypeKind tk, Path base, Path src) throws Exception {
|
|
Files.createDirectories(base.resolve("api"));
|
|
|
|
out.println("javadoc:");
|
|
try {
|
|
String s = predictOutput(sk, mk, tk, true);
|
|
Task.Expect e = s.isEmpty() ? Task.Expect.SUCCESS : Task.Expect.FAIL;
|
|
|
|
String o = new JavadocTask(tb)
|
|
.outdir(base.resolve("api"))
|
|
.options("-Xdoclint", "-Werror", "-quiet", "-sourcepath", src.toString(), "p")
|
|
.run(e)
|
|
.writeAll()
|
|
.getOutput(Task.OutputKind.DIRECT);
|
|
|
|
checkOutput(s, o);
|
|
|
|
} catch (Throwable t) {
|
|
error("Error: " + t);
|
|
}
|
|
out.println();
|
|
}
|
|
|
|
private static final String ERROR_UNEXPECTED_TEXT = "error: unexpected text";
|
|
private static final String ERROR_REFERENCE_NOT_FOUND = "error: reference not found";
|
|
private static final String WARNING_MODULE_FOR_REFERENCE_NOT_FOUND = "warning: module for reference not found: not.found";
|
|
private static final String EMPTY = "";
|
|
|
|
/**
|
|
* Returns the expected diagnostic, if any, based on the parameters of the test case.
|
|
*
|
|
* The "interesting" cases are those for which the module name is not found,
|
|
* in which case an error for "reference not found" is reduced to warning,
|
|
* which may be suppressed.
|
|
*
|
|
* @param sk whether @SuppressWarnings is present of not
|
|
* @param mk the kind of module in the reference
|
|
* @param tk the kind of class or interface name in the reference
|
|
* @param strict whether all "not found" references are errors,
|
|
* or just warnings if the module name is not found
|
|
* @return a diagnostic string, or an empty string if no diagnostic should be generated
|
|
*/
|
|
String predictOutput(SuppressKind sk, ModuleKind mk, TypeKind tk, boolean strict) {
|
|
return switch (mk) {
|
|
case NONE -> switch(tk) {
|
|
case NONE -> throw new Error("should not happen"); // filtered out in combo loops
|
|
case BAD -> ERROR_UNEXPECTED_TEXT;
|
|
case NOT_FOUND -> ERROR_REFERENCE_NOT_FOUND;
|
|
case GOOD -> EMPTY;
|
|
};
|
|
|
|
case BAD -> ERROR_UNEXPECTED_TEXT;
|
|
|
|
case NOT_FOUND -> switch(tk) {
|
|
case BAD -> ERROR_UNEXPECTED_TEXT;
|
|
case NONE, NOT_FOUND, GOOD -> strict
|
|
? ERROR_REFERENCE_NOT_FOUND
|
|
: sk == SuppressKind.YES
|
|
? EMPTY
|
|
: WARNING_MODULE_FOR_REFERENCE_NOT_FOUND;
|
|
};
|
|
|
|
case GOOD -> switch(tk) {
|
|
case BAD -> ERROR_UNEXPECTED_TEXT;
|
|
case NOT_FOUND -> ERROR_REFERENCE_NOT_FOUND;
|
|
case GOOD, NONE -> EMPTY;
|
|
};
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Checks the actual output against the expected string, generated by {@code predictError}.
|
|
* If the expected string is empty, the output should be empty.
|
|
* If the expected string is not empty, it should be present in the output.
|
|
*
|
|
* @param expect the expected string
|
|
* @param found the output
|
|
*/
|
|
void checkOutput(String expect, String found) {
|
|
if (expect.isEmpty()) {
|
|
if (found.isEmpty()) {
|
|
out.println("Output OK");
|
|
} else {
|
|
error("unexpected output");
|
|
}
|
|
} else {
|
|
if (found.contains(expect)) {
|
|
out.println("Output OK");
|
|
} else {
|
|
error("expected output not found: " + expect);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|