8190876: javadoc search on "java.se" shows "java.se" the last one among other modules
authorhannesw
Thu, 28 Jun 2018 01:46:03 +0200
changeset 50856 1857ca5aca37
parent 50855 9ca5f18240b2
child 50857 a9938374a9f4
8190876: javadoc search on "java.se" shows "java.se" the last one among other modules Reviewed-by: jjg
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchIndexItem.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
test/langtools/jdk/javadoc/doclet/testModules/TestModules.java
test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java	Wed Jun 27 16:19:28 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java	Thu Jun 28 01:46:03 2018 +0200
@@ -232,15 +232,15 @@
      */
     public TypeElement currentTypeElement = null;  // Set this TypeElement in the ClassWriter.
 
-    protected List<SearchIndexItem> memberSearchIndex = new ArrayList<>();
+    protected SortedSet<SearchIndexItem> memberSearchIndex;
 
-    protected List<SearchIndexItem> moduleSearchIndex = new ArrayList<>();
+    protected SortedSet<SearchIndexItem> moduleSearchIndex;
 
-    protected List<SearchIndexItem> packageSearchIndex = new ArrayList<>();
+    protected SortedSet<SearchIndexItem> packageSearchIndex;
 
-    protected SortedSet<SearchIndexItem> tagSearchIndex = new TreeSet<>(makeSearchTagComparator());
+    protected SortedSet<SearchIndexItem> tagSearchIndex;
 
-    protected List<SearchIndexItem> typeSearchIndex = new ArrayList<>();
+    protected SortedSet<SearchIndexItem> typeSearchIndex;
 
     protected Map<Character,List<SearchIndexItem>> tagSearchIndexMap = new HashMap<>();
 
@@ -385,16 +385,6 @@
         return htmlTag.allowTag(this.htmlVersion);
     }
 
-    public Comparator<SearchIndexItem> makeSearchTagComparator() {
-        return (SearchIndexItem sii1, SearchIndexItem sii2) -> {
-            int result = (sii1.getLabel()).compareTo(sii2.getLabel());
-            if (result == 0) {
-                result = (sii1.getHolder()).compareTo(sii2.getHolder());
-            }
-            return result;
-        };
-    }
-
     /**
      * Decide the page which will appear first in the right-hand frame. It will
      * be "overview-summary.html" if "-overview" option is used or no
@@ -883,4 +873,14 @@
         }
         return super.finishOptionSettings0();
     }
+
+    @Override
+    protected void initConfiguration(DocletEnvironment docEnv) {
+        super.initConfiguration(docEnv);
+        memberSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
+        moduleSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
+        packageSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
+        tagSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
+        typeSearchIndex = new TreeSet<>(utils.makeTypeSearchIndexComparator());
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchIndexItem.java	Wed Jun 27 16:19:28 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchIndexItem.java	Thu Jun 28 01:46:03 2018 +0200
@@ -139,4 +139,13 @@
         }
         return item.toString();
     }
+
+    /**
+     * Get the part of the label after the last dot, or whole label if no dots.
+     *
+     * @return the simple name
+     */
+    public String getSimpleName() {
+        return label.substring(label.lastIndexOf('.') + 1);
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js	Wed Jun 27 16:19:28 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js	Thu Jun 28 01:46:03 2018 +0200
@@ -24,7 +24,6 @@
  */
 
 var noResult = {l: "No results found"};
-var category = "category";
 var catModules = "Modules";
 var catPackages = "Packages";
 var catTypes = "Types";
@@ -170,25 +169,7 @@
                 return e.l.substring(e.l.lastIndexOf(".") + 1);
             }
 
-            // Sort array items by short name (as opposed to fully qualified name).
-            // Additionally, sort by the nested type name, when present,
-            // as opposed to top level short name.
-            function sortAndConcatResults(a1, a2) {
-                var sortingKey;
-                var sortArray = function(e1, e2) {
-                    var l = sortingKey(e1);
-                    var m = sortingKey(e2);
-                    if (l < m)
-                        return -1;
-                    if (l > m)
-                        return 1;
-                    return 0;
-                };
-                sortingKey = function(e) {
-                    return nestedName(e).toUpperCase();
-                };
-                a1.sort(sortArray);
-                a2.sort(sortArray);
+            function concatResults(a1, a2) {
                 a1 = a1.concat(a2);
                 a2.length = 0;
                 return a1;
@@ -197,85 +178,85 @@
             if (moduleSearchIndex) {
                 var mdleCount = 0;
                 $.each(moduleSearchIndex, function(index, item) {
-                    item[category] = catModules;
+                    item.category = catModules;
                     if (exactMatcher.test(item.l)) {
-                        result.unshift(item);
+                        result.push(item);
                         mdleCount++;
                     } else if (camelCaseMatcher.test(item.l)) {
-                        result.unshift(item);
+                        result.push(item);
                     } else if (secondaryMatcher.test(item.l)) {
                         secondaryresult.push(item);
                     }
                 });
                 displayCount = mdleCount;
-                result = sortAndConcatResults(result, secondaryresult);
+                result = concatResults(result, secondaryresult);
             }
             if (packageSearchIndex) {
                 var pCount = 0;
                 var pkg = "";
                 $.each(packageSearchIndex, function(index, item) {
-                    item[category] = catPackages;
+                    item.category = catPackages;
                     pkg = (item.m)
                             ? (item.m + "/" + item.l)
                             : item.l;
                     if (exactMatcher.test(item.l)) {
-                        presult.unshift(item);
+                        presult.push(item);
                         pCount++;
                     } else if (camelCaseMatcher.test(pkg)) {
-                        presult.unshift(item);
+                        presult.push(item);
                     } else if (secondaryMatcher.test(pkg)) {
                         secondaryresult.push(item);
                     }
                 });
-                result = result.concat(sortAndConcatResults(presult, secondaryresult));
+                result = result.concat(concatResults(presult, secondaryresult));
                 displayCount = (pCount > displayCount) ? pCount : displayCount;
             }
             if (typeSearchIndex) {
                 var tCount = 0;
                 $.each(typeSearchIndex, function(index, item) {
-                    item[category] = catTypes;
+                    item.category = catTypes;
                     var s = nestedName(item);
                     if (exactMatcher.test(s)) {
-                        tresult.unshift(item);
+                        tresult.push(item);
                         tCount++;
                     } else if (camelCaseMatcher.test(s)) {
-                        tresult.unshift(item);
+                        tresult.push(item);
                     } else if (secondaryMatcher.test(item.p + "." + item.l)) {
                         secondaryresult.push(item);
                     }
                 });
-                result = result.concat(sortAndConcatResults(tresult, secondaryresult));
+                result = result.concat(concatResults(tresult, secondaryresult));
                 displayCount = (tCount > displayCount) ? tCount : displayCount;
             }
             if (memberSearchIndex) {
                 var mCount = 0;
                 $.each(memberSearchIndex, function(index, item) {
-                    item[category] = catMembers;
+                    item.category = catMembers;
                     var s = nestedName(item);
                     if (exactMatcher.test(s)) {
-                        mresult.unshift(item);
+                        mresult.push(item);
                         mCount++;
                     } else if (camelCaseMatcher.test(s)) {
-                        mresult.unshift(item);
+                        mresult.push(item);
                     } else if (secondaryMatcher.test(item.c + "." + item.l)) {
                         secondaryresult.push(item);
                     }
                 });
-                result = result.concat(sortAndConcatResults(mresult, secondaryresult));
+                result = result.concat(concatResults(mresult, secondaryresult));
                 displayCount = (mCount > displayCount) ? mCount : displayCount;
             }
             if (tagSearchIndex) {
                 var tgCount = 0;
                 $.each(tagSearchIndex, function(index, item) {
-                    item[category] = catSearchTags;
+                    item.category = catSearchTags;
                     if (exactMatcher.test(item.l)) {
-                        tgresult.unshift(item);
+                        tgresult.push(item);
                         tgCount++;
                     } else if (secondaryMatcher.test(item.l)) {
                         secondaryresult.push(item);
                     }
                 });
-                result = result.concat(sortAndConcatResults(tgresult, secondaryresult));
+                result = result.concat(concatResults(tgresult, secondaryresult));
                 displayCount = (tgCount > displayCount) ? tgCount : displayCount;
             }
             displayCount = (displayCount > 500) ? displayCount : 500;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Wed Jun 27 16:19:28 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Thu Jun 28 01:46:03 2018 +0200
@@ -80,6 +80,7 @@
 import com.sun.source.util.DocTrees;
 import com.sun.source.util.TreePath;
 import com.sun.tools.javac.model.JavacTypes;
+import jdk.javadoc.internal.doclets.formats.html.SearchIndexItem;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.CommentUtils.DocCommentDuo;
 import jdk.javadoc.internal.doclets.toolkit.Messages;
@@ -2079,6 +2080,48 @@
         }
     }
 
+    /**
+     * Returns a Comparator for SearchIndexItems representing types. Items are
+     * compared by short name, or full string representation if names are equal.
+     *
+     * @return a Comparator
+     */
+    public Comparator<SearchIndexItem> makeTypeSearchIndexComparator() {
+        return (SearchIndexItem sii1, SearchIndexItem sii2) -> {
+            int result = compareStrings(sii1.getSimpleName(), sii2.getSimpleName());
+            if (result == 0) {
+                // TreeSet needs this to be consistent with equal so we do
+                // a plain comparison of string representations as fallback.
+                result = sii1.toString().compareTo(sii2.toString());
+            }
+            return result;
+        };
+    }
+
+    private Comparator<SearchIndexItem> genericSearchIndexComparator = null;
+    /**
+     * Returns a Comparator for SearchIndexItems representing modules, packages, or members.
+     * Items are compared by label (member name plus signature for members, package name for
+     * packages, and module name for modules). If labels are equal then full string
+     * representation is compared.
+     *
+     * @return a Comparator
+     */
+    public Comparator<SearchIndexItem> makeGenericSearchIndexComparator() {
+        if (genericSearchIndexComparator == null) {
+            genericSearchIndexComparator = (SearchIndexItem sii1, SearchIndexItem sii2) -> {
+                int result = compareStrings(sii1.getLabel(), sii2.getLabel());
+                if (result == 0) {
+                    // TreeSet needs this to be consistent with equal so we do
+                    // a plain comparison of string representations as fallback.
+                    result = sii1.toString().compareTo(sii2.toString());
+                }
+                return result;
+            };
+        }
+        return genericSearchIndexComparator;
+    }
+
     public Iterable<TypeElement> getEnclosedTypeElements(PackageElement pkg) {
         List<TypeElement> out = getInterfaces(pkg);
         out.addAll(getClasses(pkg));
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Wed Jun 27 16:19:28 2018 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Thu Jun 28 01:46:03 2018 +0200
@@ -1171,12 +1171,12 @@
                 + "</dd>\n"
                 + "</dl>",
                 "<dl>\n"
+                + "<dt><span class=\"searchTagLink\"><a href=\"moduleB/module-summary.html#search_word\">"
+                + "search_word</a></span> - Search tag in moduleB</dt>\n"
+                + "<dd>&nbsp;</dd>\n"
                 + "<dt><span class=\"searchTagLink\"><a href=\"moduleA/module-summary.html#searchphrase\">"
                 + "search phrase</a></span> - Search tag in moduleA</dt>\n"
                 + "<dd>with description</dd>\n"
-                + "<dt><span class=\"searchTagLink\"><a href=\"moduleB/module-summary.html#search_word\">"
-                + "search_word</a></span> - Search tag in moduleB</dt>\n"
-                + "<dd>&nbsp;</dd>\n"
                 + "</dl>");
         checkOutput("index-all.html", false,
                 "<dt><span class=\"searchTagLink\"><a href=\"moduleA/module-summary.html#searchphrase\">"
--- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Wed Jun 27 16:19:28 2018 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Thu Jun 28 01:46:03 2018 +0200
@@ -631,9 +631,9 @@
                 "camelCaseMatcher.test(item.l)",
                 "var secondaryresult = new Array();",
                 "function nestedName(e) {",
-                "function sortAndConcatResults(a1, a2) {",
+                "function concatResults(a1, a2) {",
                 "if (exactMatcher.test(item.l)) {\n"
-                + "                        presult.unshift(item);",
+                + "                        presult.push(item);",
                 "$(\"#search\").on('click keydown', function() {\n"
                 + "        if ($(this).val() == watermark) {\n"
                 + "            $(this).val('').removeClass('watermark');\n"