|
@@ -24,26 +24,37 @@ |
|
|
/* |
|
|
* @test |
|
|
* @bug 4494033 7028815 7052425 8007338 8023608 8008164 8016549 8072461 8154261 8162363 8160196 8151743 8177417 |
|
|
* 8175218 8176452 8181215 8182263 8183511 8169819 8183037 8185369 8182765 8196201 8184205 8223378 |
|
|
* 8175218 8176452 8181215 8182263 8183511 8169819 8183037 8185369 8182765 8196201 8184205 8223378 8241544 |
|
|
* @summary Run tests on doclet stylesheet. |
|
|
* @library ../../lib |
|
|
* @library /tools/lib ../../lib |
|
|
* @modules jdk.javadoc/jdk.javadoc.internal.tool |
|
|
* @build javadoc.tester.* |
|
|
* @build toolbox.ToolBox javadoc.tester.* |
|
|
* @run main TestStylesheet |
|
|
*/ |
|
|
|
|
|
import java.io.IOException; |
|
|
import java.io.PrintStream; |
|
|
import java.nio.file.Path; |
|
|
import java.util.List; |
|
|
import java.util.Map; |
|
|
import java.util.Set; |
|
|
import java.util.TreeSet; |
|
|
import java.util.function.Function; |
|
|
|
|
|
import javadoc.tester.HtmlChecker; |
|
|
import javadoc.tester.JavadocTester; |
|
|
import toolbox.ToolBox; |
|
|
|
|
|
public class TestStylesheet extends JavadocTester { |
|
|
|
|
|
public static void main(String... args) throws Exception { |
|
|
TestStylesheet tester = new TestStylesheet(); |
|
|
tester.runTests(); |
|
|
tester.runTests(m -> new Object[] { Path.of(m.getName())}); |
|
|
} |
|
|
|
|
|
@Test |
|
|
public void test() { |
|
|
javadoc("-d", "out", |
|
|
public void test(Path base) { |
|
|
javadoc("-d", base.resolve("out").toString(), |
|
|
"-sourcepath", testSrc, |
|
|
"pkg"); |
|
|
checkExit(Exit.ERROR); |
|
@@ -233,4 +244,183 @@ public void test() { |
|
|
+ " font-weight:bold;\n" |
|
|
+ "}"); |
|
|
} |
|
|
|
|
|
ToolBox tb = new ToolBox(); |
|
|
|
|
|
@Test |
|
|
public void testStyles(Path base) throws Exception { |
|
|
Path src = base.resolve("src"); |
|
|
tb.writeJavaFiles(src, |
|
|
"module mA { exports p; }", |
|
|
"package p; public class C {\n" |
|
|
+ "public C() { }\n" |
|
|
+ "public C(int i) { }\n" |
|
|
+ "public int f1;\n" |
|
|
+ "public int f2;\n" |
|
|
+ "public int m1() { }\n" |
|
|
+ "public int m2(int i) { }\n" |
|
|
+ "}\n", |
|
|
"package p; public @interface Anno {\n" |
|
|
+ "public int value();\n" |
|
|
+ "}\n" |
|
|
); |
|
|
|
|
|
javadoc("-d", base.resolve("out").toString(), |
|
|
"-sourcepath", src.toString(), |
|
|
"--module", "mA"); |
|
|
checkExit(Exit.OK); |
|
|
checkStyles(addExtraCSSClassNamesTo(readStylesheet())); |
|
|
} |
|
|
|
|
|
Set<String> readStylesheet() { |
|
|
// scan for class selectors, skipping '{' ... '}' |
|
|
Set<String> styles = new TreeSet<>(); |
|
|
String stylesheet = readFile("stylesheet.css"); |
|
|
for (int i = 0; i < stylesheet.length(); i++) { |
|
|
char ch = stylesheet.charAt(i); |
|
|
switch (ch) { |
|
|
case '.': |
|
|
i++; |
|
|
int start = i; |
|
|
while (i < stylesheet.length()) { |
|
|
ch = stylesheet.charAt(i); |
|
|
if (!(Character.isLetterOrDigit(ch) || ch == '-')) { |
|
|
break; |
|
|
} |
|
|
i++; |
|
|
} |
|
|
styles.add(stylesheet.substring(start, i)); |
|
|
break; |
|
|
|
|
|
case '{': |
|
|
i++; |
|
|
while (i < stylesheet.length()) { |
|
|
ch = stylesheet.charAt(i); |
|
|
if (ch == '}') { |
|
|
break; |
|
|
} |
|
|
i++; |
|
|
} |
|
|
break; |
|
|
|
|
|
case '@': |
|
|
i++; |
|
|
while (i < stylesheet.length()) { |
|
|
ch = stylesheet.charAt(i); |
|
|
if (ch == '{') { |
|
|
break; |
|
|
} |
|
|
i++; |
|
|
} |
|
|
break; |
|
|
} |
|
|
} |
|
|
out.println("found styles: " + styles); |
|
|
return styles; |
|
|
} |
|
|
|
|
|
Set<String> addExtraCSSClassNamesTo(Set<String> styles) throws Exception { |
|
|
// The following names are used in the generated HTML, |
|
|
// but have no corresponding definitions in the stylesheet file. |
|
|
// They are mostly optional, in the "use if you want to" category. |
|
|
// They are included here so that we do not get errors when these |
|
|
// names are used in the generated HTML. |
|
|
List<String> extra = List.of( |
|
|
// entries for <body> elements |
|
|
"all-classes-index-page", |
|
|
"all-packages-index-page", |
|
|
"constants-summary-page", |
|
|
"deprecated-list-page", |
|
|
"help-page", |
|
|
"index-redirect-page", |
|
|
"package-declaration-page", |
|
|
"package-tree-page", |
|
|
"single-index-page", |
|
|
"tree-page", |
|
|
// the following names are matched by [class$='...'] in the stylesheet |
|
|
"constructor-details", |
|
|
"constructor-summary", |
|
|
"field-details", |
|
|
"field-summary", |
|
|
"member-details", |
|
|
"method-details", |
|
|
"method-summary", |
|
|
// the following provide the ability to optionally override components of the |
|
|
// memberSignature structure |
|
|
"member-name", |
|
|
"modifiers", |
|
|
"packages", |
|
|
"return-type", |
|
|
// and others... |
|
|
"help-section", // part of the help page |
|
|
"hierarchy", // for the hierarchy on a tree page |
|
|
"index" // on the index page |
|
|
); |
|
|
Set<String> all = new TreeSet<>(styles); |
|
|
for (String e : extra) { |
|
|
if (styles.contains(e)) { |
|
|
throw new Exception("extra CSS class name found in style sheet: " + e); |
|
|
} |
|
|
all.add(e); |
|
|
} |
|
|
return all; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Checks that all the CSS names found in {@code class} attributes in HTML files in the |
|
|
* output directory are present in a given set of styles. |
|
|
* |
|
|
* @param styles the styles |
|
|
*/ |
|
|
void checkStyles(Set<String> styles) { |
|
|
checking("Check CSS class names"); |
|
|
CSSClassChecker c = new CSSClassChecker(out, this::readFile, styles); |
|
|
try { |
|
|
c.checkDirectory(outputDir.toPath()); |
|
|
c.report(); |
|
|
int errors = c.getErrorCount(); |
|
|
if (errors == 0) { |
|
|
passed("No CSS class name errors found"); |
|
|
} else { |
|
|
failed(errors + " errors found when checking CSS class names"); |
|
|
} |
|
|
} catch (IOException e) { |
|
|
failed("exception thrown when reading files: " + e); |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
class CSSClassChecker extends HtmlChecker { |
|
|
Set<String> styles; |
|
|
int errors; |
|
|
|
|
|
protected CSSClassChecker(PrintStream out, |
|
|
Function<Path, String> fileReader, |
|
|
Set<String> styles) { |
|
|
super(out, fileReader); |
|
|
this.styles = styles; |
|
|
} |
|
|
|
|
|
protected int getErrorCount() { |
|
|
return errors; |
|
|
} |
|
|
|
|
|
@Override |
|
|
protected void report() { |
|
|
if (getErrorCount() == 0) { |
|
|
out.println("All CSS class names found"); |
|
|
} else { |
|
|
out.println(getErrorCount() + " CSS class names not found"); |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
@Override |
|
|
public void startElement(String name, Map<String,String> attrs, boolean selfClosing) { |
|
|
String style = attrs.get("class"); |
|
|
if (style != null && !styles.contains(style)) { |
|
|
error(currFile, getLineNumber(), "CSS class name not found: " + style); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |