From ab85eea3a337662b2c875b96ad5eb057995dbbe2 Mon Sep 17 00:00:00 2001 From: Alexander Kriegisch Date: Sun, 21 Mar 2021 21:45:34 +0700 Subject: [PATCH] Add Java 16 Linux matcher variant to HtmlDecorator The Java 16 Javadoc generator has changed the HTML structure once again even compared to Java 15. I adjusted the matching in HtmlDecorator and also fixed CoverageTestCase. Most methods there I just made to work quickly, but method 'testInnerAspect()' I actually refactored. Some other methods could (probably should) be restructured in a similar fashion, but for now I just wanted to understand what the test does and see how much work it would be to refactor it. But finally, I just want to get the GitHub CI build running on Java 16. TODO: I did not check if the decorated HTML actually looks OK and am unsure if the tests cover that sufficiently, I never reviewed the tests. It would also be better to do regex matches instead of looking for variants of fixed strings or maybe even to operate on a DOM. But I am not in a mood to refactor that tonight. Signed-off-by: Alexander Kriegisch --- .../aspectj/tools/ajdoc/HtmlDecorator.java | 61 ++++--- .../aspectj/tools/ajdoc/CoverageTestCase.java | 150 ++++++++++-------- 2 files changed, 121 insertions(+), 90 deletions(-) diff --git a/ajdoc/src/main/java/org/aspectj/tools/ajdoc/HtmlDecorator.java b/ajdoc/src/main/java/org/aspectj/tools/ajdoc/HtmlDecorator.java index 17dcaab9c..56565e05a 100644 --- a/ajdoc/src/main/java/org/aspectj/tools/ajdoc/HtmlDecorator.java +++ b/ajdoc/src/main/java/org/aspectj/tools/ajdoc/HtmlDecorator.java @@ -39,9 +39,24 @@ import org.aspectj.util.TypeSafeEnum; */ class HtmlDecorator { - public static final String TYPE_NAME_LABEL = LangUtil.is15VMOrGreater() - ? "type-name-label" - : (LangUtil.is1dot8VMOrGreater() ? "typeNameLabel" : "strong"); + public static final String TYPE_NAME_LABEL; + public static final String CLOSING_SPAN; + + static { + if (LangUtil.is16VMOrGreater()) + TYPE_NAME_LABEL = "element-name type-name-label"; + else if (LangUtil.is15VMOrGreater()) + TYPE_NAME_LABEL = "type-name-label"; + else if (LangUtil.is1dot8VMOrGreater()) + TYPE_NAME_LABEL = "typeNameLabel"; + else + TYPE_NAME_LABEL = "strong"; + + if (LangUtil.is16VMOrGreater()) + CLOSING_SPAN = ""; + else + CLOSING_SPAN = ""; + } private static final String POINTCUT_DETAIL = "Pointcut Detail"; private static final String ADVICE_DETAIL = "Advice Detail"; @@ -223,33 +238,35 @@ class HtmlDecorator { } boolean br = true; - int classStartIndex = fileContents.toString().indexOf("
\nClass "); + contents = fileContents.toString(); + int classStartIndex = contents.indexOf("
\nClass "); if (classStartIndex == -1) { - classStartIndex = fileContents.toString().indexOf("

\nClass "); + classStartIndex = contents.indexOf("

\nClass "); br = false; } if (classStartIndex == -1) { // Java8 looks more like this: //

Class A

- classStartIndex = fileContents.toString().indexOf("

", classStartIndex); + classStartIndex = contents.indexOf("

", classStartIndex); if (classStartIndex == -1) { // Java 13 - replaced h2 with h1 here - classStartIndex = fileContents.toString().indexOf("

", classStartIndex); + classStartIndex = contents.indexOf("

", classStartIndex); } if (classEndIndex != -1) { // Convert it to "

Aspect A

" - String classLine = fileContents.toString().substring(classStartIndex, classEndIndex); + String classLine = contents.substring(classStartIndex, classEndIndex); String aspectLine = classLine.replaceAll("Class ","Aspect "); fileContents.delete(classStartIndex, classEndIndex); fileContents.insert(classStartIndex, aspectLine); } } else if (classStartIndex != -1) { - int classEndIndex = fileContents.toString().indexOf("", classStartIndex); - if (classStartIndex != -1 && classEndIndex != -1) { - String classLine = fileContents.toString().substring(classStartIndex, classEndIndex); + contents = fileContents.toString(); + int classEndIndex = contents.indexOf("", classStartIndex); + if (classEndIndex != -1) { + String classLine = contents.substring(classStartIndex, classEndIndex); String aspectLine = ""; if (br) { aspectLine += "
\n" + "Aspect " + classLine.substring(11, classLine.length()); @@ -260,23 +277,27 @@ class HtmlDecorator { fileContents.insert(classStartIndex, aspectLine); } } - int secondClassStartIndex = fileContents.toString().indexOf("class "); + contents = fileContents.toString(); + int secondClassStartIndex = contents.indexOf("class "); if (secondClassStartIndex != -1) { String name = decl.toSignatureString(); - int classEndIndex = fileContents.toString().indexOf(name + "
"); - if (secondClassStartIndex != -1 && classEndIndex != -1) { - StringBuffer sb = new StringBuffer(fileContents.toString().substring(secondClassStartIndex, classEndIndex)); + int classEndIndex = contents.indexOf(name + "
"); + if (classEndIndex != -1) { + StringBuffer sb = new StringBuffer(contents.substring(secondClassStartIndex, classEndIndex)); sb.replace(0, 5, "aspect"); fileContents.delete(secondClassStartIndex, classEndIndex); fileContents.insert(secondClassStartIndex, sb.toString()); } } else { + contents = fileContents.toString(); + // Java16: static class ClassA.InnerAspect // Java15:
static class ClassA.InnerAspect
 					// Java8: 
static class ClassA.InnerAspect
 					// Java7 (464604): 
public class Azpect
-					classStartIndex = fileContents.toString().indexOf("class ");
-					int classEndIndex = fileContents.toString().indexOf("", classStartIndex);
+					String startString = "class " + CLOSING_SPAN + "");
+					int classEndIndex = contents.indexOf("", classStartIndex + startString.length());
 
 					// This is where after Java version upgrades usually tests fail or the first time.
 					// Logging context information helps fixing the issue quickly.
@@ -291,7 +312,7 @@ class HtmlDecorator {
 
 					if (classEndIndex != -1) {
 						// Convert it to "aspect ClassA.InnerAspect"
-						String aspectLine = "aspect" + fileContents.substring(classStartIndex + 5, classEndIndex);
+						String aspectLine = "aspect" + contents.substring(classStartIndex + 5, classEndIndex);
 						fileContents.delete(classStartIndex, classEndIndex);
 						fileContents.insert(classStartIndex, aspectLine);
 					}
diff --git a/ajdoc/src/test/java/org/aspectj/tools/ajdoc/CoverageTestCase.java b/ajdoc/src/test/java/org/aspectj/tools/ajdoc/CoverageTestCase.java
index 17f0bc9c4..ab2fc8ec2 100644
--- a/ajdoc/src/test/java/org/aspectj/tools/ajdoc/CoverageTestCase.java
+++ b/ajdoc/src/test/java/org/aspectj/tools/ajdoc/CoverageTestCase.java
@@ -16,6 +16,7 @@ import java.util.List;
 
 import org.aspectj.util.LangUtil;
 
+import static org.aspectj.tools.ajdoc.HtmlDecorator.CLOSING_SPAN;
 import static org.aspectj.tools.ajdoc.HtmlDecorator.TYPE_NAME_LABEL;
 
 /**
@@ -117,67 +118,76 @@ public class CoverageTestCase extends AjdocTestCase {
      * Test that the ajdoc for an inner aspect is entitled "Aspect" rather
      * than "Class", but that the enclosing class is still "Class"
      */
-    public void testInnerAspect() throws Exception {
-    	File[] files = {file1, file2};
-        runAjdoc("private",AJDocConstants.VERSION,files);
-
-        File htmlFile = new File(getAbsolutePathOutdir() + "/foo/ClassA.InnerAspect.html");
-		if (!htmlFile.exists()) {
-			fail("couldn't find " + htmlFile.getAbsolutePath()
-					+ " - were there compilation errors?");
-		}
-
-		// ensure that the file is entitled "Aspect ClassA.InnerAspect" rather
-		// than "Class ClassA.InnerAspect"
+		public void testInnerAspect() throws Exception {
+			File[] files = { file1, file2 };
+			runAjdoc("private", AJDocConstants.VERSION, files);
 
-		String[] strings = null;
-		strings = new String[] {
-			"Aspect ClassA.InnerAspect",
-			"
static aspect ClassA.InnerAspect",
-			"Class ClassA.InnerAspect",
-			"
static class ClassA.InnerAspect"};
-		List missingStrings = AjdocOutputChecker.getMissingStringsInFile(htmlFile,strings);
-		StringBuilder buf = new StringBuilder();
-		for (String str:missingStrings) {
-			buf.append(str).append("\n");
-		}
-		buf.append("HTMLFILE=\n").append(htmlFile).append("\n");
-		assertEquals("There should be 2 missing strings:\n"+buf.toString(), 2, missingStrings.size());
-		assertTrue(htmlFile.getName() + " should not have Class as it's title",
-				missingStrings.contains("Class ClassA.InnerAspect"));
-		assertTrue(htmlFile.getName() + " should not have class in its subtitle",
-				missingStrings.contains("
static class ClassA.InnerAspect"));
+			// Get the HTML file for the inner aspect
+			File htmlFile = new File(getAbsolutePathOutdir() + "/foo/ClassA.InnerAspect.html");
+			if (!htmlFile.exists()) {
+				fail("couldn't find " + htmlFile.getAbsolutePath() + " - were there compilation errors?");
+			}
 
-		// get the html file for the enclosing class
-        File htmlFileClass = new File(getAbsolutePathOutdir() + "/foo/ClassA.html");
-		if (!htmlFileClass.exists()) {
-			fail("couldn't find " + htmlFileClass.getAbsolutePath()
-					+ " - were there compilation errors?");
-		}
+			// Ensure that the file is entitled "Aspect ClassA.InnerAspect" rather than "Class ClassA.InnerAspect"
+
+			String[] strings = new String[] {
+				// These 2 should be missing because they reference "class", not "aspect"
+				"Class ClassA.InnerAspect",
+				"static class " + CLOSING_SPAN + "ClassA.InnerAspect",
+				// These 2 should be present  (i.e. 0 missing) after AJ doc creation
+				"Aspect ClassA.InnerAspect",
+				"static aspect " + CLOSING_SPAN + "ClassA.InnerAspect"
+			};
+			List missingStrings = AjdocOutputChecker.getMissingStringsInFile(htmlFile, strings);
+
+			StringBuilder buf = new StringBuilder();
+			buf.append("HTML file = ").append(htmlFile).append("\nMissing strings:\n");
+			for (String str : missingStrings)
+				buf.append(str).append("\n");
+
+			assertEquals(
+				"In " + htmlFile.getName() + " there should be 2 missing strings:\n" + buf,
+				2, missingStrings.size()
+			);
+			assertEquals(
+				"In " + htmlFile.getName() + " no missing string should be aspect-related:\n" + buf,
+				0, missingStrings.stream().filter(s -> s.contains("static aspect")).count()
+			);
+
+			// Get the HTML file for the enclosing class
+			htmlFile = new File(getAbsolutePathOutdir() + "/foo/ClassA.html");
+			if (!htmlFile.exists()) {
+				fail("couldn't find " + htmlFile.getAbsolutePath() + " - were there compilation errors?");
+			}
 
-		// ensure that the file is entitled "Class ClassA" and
-		// has not been changed to "Aspect ClassA"
-		String[] classStrings = null;
+			// Ensure that the file is entitled "Class ClassA" and has not been changed to "Aspect ClassA"
 
-		if (LangUtil.is13VMOrGreater()) {
-			classStrings = new String[] {
-				"Class ClassA",
-				"public abstract class ClassA",
+			strings = new String[] {
+				// These 3 should be missing because they reference "aspect", not "class"
 				"Aspect ClassA",
-				"public abstract aspect ClassA"};
-		} else {
-			classStrings = new String[] {
+				"Aspect ClassA",
+				"public abstract aspect " + CLOSING_SPAN + "ClassA",
+				// Of these 3, 2 should be present  (i.e. 1 missing) after AJ doc creation
+				"Class ClassA",
 				"Class ClassA",
-				"public abstract class ClassA",
-				"Aspect ClassA",
-				"public abstract aspect ClassA"};
+				"public abstract class " + CLOSING_SPAN + "ClassA"
+			};
+			missingStrings = AjdocOutputChecker.getMissingStringsInFile(htmlFile, strings);
+
+			buf = new StringBuilder();
+			buf.append("HTML file = ").append(htmlFile).append("\nMissing strings:\n");
+			for (String str : missingStrings)
+				buf.append(str).append("\n");
+
+			assertEquals(
+				"In " + htmlFile.getName() + " there should be 4 missing strings:\n" + buf,
+				4, missingStrings.size()
+			);
+			assertEquals(
+				"In " + htmlFile.getName() + " 3 missing string should be aspect-related:\n" + buf,
+				3, missingStrings.stream().filter(s -> s.contains("abstract aspect") || s.contains("Aspect ClassA")).count()
+			);
 		}
-		List classMissing = AjdocOutputChecker.getMissingStringsInFile(htmlFileClass,classStrings);
-		assertEquals("There should be 2 missing strings:\n"+classMissing,2,classMissing.size());
-		assertTrue(htmlFileClass.getName() + " should not have Aspect as it's title",classMissing.contains("Aspect ClassA"));
-		assertTrue(htmlFileClass.getName() + " should not have aspect in its subtitle",
-				classMissing.contains("public abstract aspect ClassA"));
-	}
 
     /**
      * Test that all the different types of advice appear
@@ -659,9 +669,9 @@ public class CoverageTestCase extends AjdocTestCase {
 		String[] strings = null;
 		strings = new String[] {
 				"Aspect PkgVisibleClass.NestedAspect",
-				"
static aspect PkgVisibleClass.NestedAspect",
+				"static aspect " + CLOSING_SPAN + "PkgVisibleClass.NestedAspect",
 				"Class PkgVisibleClass.NestedAspect",
-				"
static class PkgVisibleClass.NestedAspect"};
+				"static class " + CLOSING_SPAN + "PkgVisibleClass.NestedAspect"};
 		List missingStrings = AjdocOutputChecker.getMissingStringsInFile(htmlFile,strings);
 		StringBuilder buf = new StringBuilder();
 		for (String str:missingStrings) {
@@ -671,7 +681,7 @@ public class CoverageTestCase extends AjdocTestCase {
 		assertEquals("There should be 2 missing strings",2,missingStrings.size());
 		assertTrue(htmlFile.getName() + " should not have Class as it's title",missingStrings.contains("Class PkgVisibleClass.NestedAspect"));
 		assertTrue(htmlFile.getName() + " should not have class in its subtitle",
-				missingStrings.contains("
static class PkgVisibleClass.NestedAspect"));
+				missingStrings.contains("static class " + CLOSING_SPAN + "PkgVisibleClass.NestedAspect"));
 		// get the html file for the enclosing class
         File htmlFileClass = new File(getAbsolutePathOutdir() + "/PkgVisibleClass.html");
 		if (!htmlFileClass.exists()) {
@@ -685,22 +695,22 @@ public class CoverageTestCase extends AjdocTestCase {
 		if (LangUtil.is13VMOrGreater()) {
 			classStrings = new String[] {
 				"Class PkgVisibleClass",
-				"
class PkgVisibleClass",
+				"class " + CLOSING_SPAN + "PkgVisibleClass",
 				"Aspect PkgVisibleClass",
-				"
aspect PkgVisibleClass"};
+				"aspect " + CLOSING_SPAN + "PkgVisibleClass"};
 		} else {
 			classStrings = new String[] {
 				"Class PkgVisibleClass",
-				"
class PkgVisibleClass",
+				"class " + CLOSING_SPAN + "PkgVisibleClass",
 				"Aspect PkgVisibleClass",
-				"
aspect PkgVisibleClass"};
+				"aspect " + CLOSING_SPAN + "PkgVisibleClass"};
 		}
 		List classMissing = AjdocOutputChecker.getMissingStringsInFile(htmlFileClass,classStrings);
 		assertEquals("There should be 2 missing strings",2,classMissing.size());
 		assertTrue(htmlFileClass.getName() + " should not have Aspect as it's title",
 				classMissing.contains("Aspect PkgVisibleClass"));
 		assertTrue(htmlFileClass.getName() + " should not have aspect in its subtitle",
-				classMissing.contains("
aspect PkgVisibleClass"));
+				classMissing.contains("aspect " + CLOSING_SPAN + "PkgVisibleClass"));
 	}
 
 	/**
@@ -723,9 +733,9 @@ public class CoverageTestCase extends AjdocTestCase {
 		String[] strings = null;
 		strings = new String [] {
 			"Aspect ClassWithNestedAspect.NestedAspect",
-			"
static aspect ClassWithNestedAspect.NestedAspect",
+			"static aspect " + CLOSING_SPAN + "ClassWithNestedAspect.NestedAspect",
 			"Class ClassWithNestedAspect.NestedAspect",
-			"
static class ClassWithNestedAspect.NestedAspect"};
+			"static class " + CLOSING_SPAN + "ClassWithNestedAspect.NestedAspect"};
 		List missingStrings = AjdocOutputChecker.getMissingStringsInFile(htmlFile,strings);
 		StringBuilder buf = new StringBuilder();
 		for (String str:missingStrings) {
@@ -735,7 +745,7 @@ public class CoverageTestCase extends AjdocTestCase {
 		assertEquals("There should be 2 missing strings",2,missingStrings.size());
 		assertTrue(htmlFile.getName() + " should not have Class as it's title",missingStrings.contains("Class ClassWithNestedAspect.NestedAspect"));
 		assertTrue(htmlFile.getName() + " should not have class in its subtitle",
-				missingStrings.contains("
static class ClassWithNestedAspect.NestedAspect"));
+				missingStrings.contains("static class " + CLOSING_SPAN + "ClassWithNestedAspect.NestedAspect"));
 
 		// get the html file for the enclosing class
         File htmlFileClass = new File(getAbsolutePathOutdir() + "/pkg/ClassWithNestedAspect.html");
@@ -750,22 +760,22 @@ public class CoverageTestCase extends AjdocTestCase {
 		if (LangUtil.is13VMOrGreater()) {
 			classStrings = new String[] {
 				"Class ClassWithNestedAspect",
-				"public class ClassWithNestedAspect",
+				"public class " + CLOSING_SPAN + "ClassWithNestedAspect",
 				"Aspect ClassWithNestedAspect",
-				"public aspect ClassWithNestedAspect"};
+				"public aspect " + CLOSING_SPAN + "ClassWithNestedAspect"};
 		} else {
 			classStrings = new String[] {
 				"Class ClassWithNestedAspect",
-				"public class ClassWithNestedAspect",
+				"public class " + CLOSING_SPAN + "ClassWithNestedAspect",
 				"Aspect ClassWithNestedAspect",
-				"public aspect ClassWithNestedAspect"};
+				"public aspect " + CLOSING_SPAN + "ClassWithNestedAspect"};
 		}
 		List classMissing = AjdocOutputChecker.getMissingStringsInFile(htmlFileClass,classStrings);
 		assertEquals("There should be 2 missing strings",2,classMissing.size());
 		assertTrue(htmlFileClass.getName() + " should not have Aspect as it's title",
 				classMissing.contains("Aspect ClassWithNestedAspect"));
 		assertTrue(htmlFileClass.getName() + " should not have aspect in its subtitle",
-				classMissing.contains("public aspect ClassWithNestedAspect"));
+				classMissing.contains("public aspect " + CLOSING_SPAN + "ClassWithNestedAspect"));
 	}
 
 	/**
-- 
2.39.5