8247994: Localize javadoc search

Reviewed-by: hannesw, ihse
This commit is contained in:
Jonathan Gibbons 2020-12-17 18:34:27 +00:00
parent 47c180da43
commit 30ca0a5d4b
9 changed files with 114 additions and 33 deletions

View File

@ -74,7 +74,7 @@ define SetupInterimModule
EXCLUDE_FILES := $(TOPDIR)/src/$1/share/classes/module-info.java \
Standard.java, \
EXTRA_FILES := $(BUILDTOOLS_OUTPUTDIR)/gensrc/$1.interim/module-info.java, \
COPY := .gif .png .xml .css .js .txt javax.tools.JavaCompilerTool, \
COPY := .gif .png .xml .css .js .js.template .txt javax.tools.JavaCompilerTool, \
BIN := $(BUILDTOOLS_OUTPUTDIR)/interim_langtools_modules/$1.interim, \
DISABLED_WARNINGS := module options, \
JAVAC_FLAGS := \

View File

@ -339,7 +339,7 @@ jdk.dynalink_CLEAN += .properties
################################################################################
jdk.javadoc_COPY += .xml .css .js .png .txt
jdk.javadoc_COPY += .xml .css .js .js.template .png .txt
################################################################################

View File

@ -32,7 +32,6 @@ import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import jdk.javadoc.doclet.Doclet;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.Reporter;
import jdk.javadoc.internal.doclets.toolkit.AbstractDoclet;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
@ -216,7 +215,7 @@ public class HtmlDoclet extends AbstractDoclet {
f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.JAVASCRIPT), true, true);
if (options.createIndex()) {
f = DocFile.createFileForOutput(configuration, DocPaths.SEARCH_JS);
f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.SEARCH_JS), true, true);
f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.SEARCH_JS_TEMPLATE), configuration.docResources);
f = DocFile.createFileForOutput(configuration, DocPaths.RESOURCES.resolve(DocPaths.GLASS_IMG));
f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.GLASS_IMG), true, false);

View File

@ -23,13 +23,13 @@
* questions.
*/
var noResult = {l: "No results found"};
var loading = {l: "Loading search index..."};
var catModules = "Modules";
var catPackages = "Packages";
var catTypes = "Types";
var catMembers = "Members";
var catSearchTags = "SearchTags";
var noResult = {l: "##REPLACE:doclet.search.no_results##"};
var loading = {l: "##REPLACE:doclet.search.loading##"};
var catModules = "##REPLACE:doclet.search.modules##";
var catPackages = "##REPLACE:doclet.search.packages##";
var catTypes = "##REPLACE:doclet.search.types##";
var catMembers = "##REPLACE:doclet.search.members##";
var catSearchTags = "##REPLACE:doclet.search.search_tags##";
var highlight = "<span class=\"result-highlight\">$&</span>";
var searchPattern = "";
var fallbackPattern = "";

View File

@ -333,3 +333,11 @@ doclet.record_field_doc.fullbody=\
doclet.platform.docs.old=https://docs.oracle.com/javase/{0}/docs/api/
doclet.platform.docs.new=https://docs.oracle.com/en/java/javase/{0}/docs/api/
doclet.platform.docs.ea=https://download.java.net/java/early_access/jdk{0}/docs/api/
doclet.search.no_results=No results found
doclet.search.loading=Loading search index...
doclet.search.modules=Modules
doclet.search.packages=Packages
doclet.search.types=Types
doclet.search.members=Members
doclet.search.search_tags=Search Tags

View File

@ -32,12 +32,17 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.MissingResourceException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.tools.DocumentationTool;
import javax.tools.FileObject;
import javax.tools.JavaFileManager.Location;
import javax.tools.StandardLocation;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Resources;
/**
* Abstraction for handling files, which may be specified directly
@ -175,10 +180,28 @@ public abstract class DocFile {
* @throws ResourceIOException if there is a problem while reading the resource
*/
public void copyResource(DocPath resource, boolean overwrite, boolean replaceNewLine)
throws DocFileIOException, ResourceIOException {
throws DocFileIOException, ResourceIOException {
if (exists() && !overwrite)
return;
copyResource(resource, replaceNewLine, null);
}
/**
* Copy the contents of a resource file to this file.
*
* @param resource the path of the resource, relative to the package of this class
* @param resources if not {@code null}, substitute occurrences of {@code ##REPLACE:key##}
*
* @throws DocFileIOException if there is a problem while writing the copy
* @throws ResourceIOException if there is a problem while reading the resource
*/
public void copyResource(DocPath resource, Resources resources) throws DocFileIOException, ResourceIOException {
copyResource(resource, true, resources);
}
private void copyResource(DocPath resource, boolean replaceNewLine, Resources resources)
throws DocFileIOException, ResourceIOException {
try {
InputStream in = BaseConfiguration.class.getResourceAsStream(resource.getPath());
if (in == null)
@ -190,7 +213,7 @@ public abstract class DocFile {
try (Writer writer = openWriter()) {
String line;
while ((line = readResourceLine(resource, reader)) != null) {
write(this, writer, line);
write(this, writer, resources == null ? line : localize(line, resources));
write(this, writer, DocletConstants.NL);
}
} catch (IOException e) {
@ -216,6 +239,32 @@ public abstract class DocFile {
}
}
private static final Pattern replacePtn = Pattern.compile("##REPLACE:(?<key>[A-Za-z0-9._]+)##");
private String localize(String line, Resources resources) {
Matcher m = replacePtn.matcher(line);
StringBuilder sb = null;
int start = 0;
while (m.find()) {
if (sb == null) {
sb = new StringBuilder();
}
sb.append(line, start, m.start());
try {
sb.append(resources.getText(m.group("key")));
} catch (MissingResourceException e) {
sb.append(m.group());
}
start = m.end();
}
if (sb == null) {
return line;
} else {
sb.append(line.substring(start));
return sb.toString();
}
}
/** Return true if the file can be read. */
public abstract boolean canRead();
@ -279,11 +328,12 @@ public abstract class DocFile {
/**
* Reads from an input stream opened from a given file into a given buffer.
* If an IOException occurs, it is wrapped in a DocFileIOException.
* If an {@code IOException} occurs, it is wrapped in a {@code DocFileIOException}.
*
* @param inFile the file for the stream
* @param input the stream
* @param buf the buffer
* @param input the stream
* @param buf the buffer
*
* @return the number of bytes read, or -1 if at end of file
* @throws DocFileIOException if an exception occurred while reading the stream
*/
@ -297,11 +347,12 @@ public abstract class DocFile {
/**
* Writes to an output stream for a given file from a given buffer.
* If an IOException occurs, it is wrapped in a DocFileIOException.
* If an {@code IOException} occurs, it is wrapped in a {@code DocFileIOException}.
*
* @param outFile the file for the stream
* @param out the stream
* @param buf the buffer
* @param out the stream
* @param buf the buffer
*
* @throws DocFileIOException if an exception occurred while writing the stream
*/
private static void write(DocFile outFile, OutputStream out, byte[] buf, int len) throws DocFileIOException {
@ -314,11 +365,12 @@ public abstract class DocFile {
/**
* Writes text to an output stream for a given file from a given buffer.
* If an IOException occurs, it is wrapped in a DocFileIOException.
* If an {@code IOException} occurs, it is wrapped in a {@code DocFileIOException}.
*
* @param outFile the file for the stream
* @param out the stream
* @param text the text to be written
* @param out the stream
* @param text the text to be written
*
* @throws DocFileIOException if an exception occurred while writing the stream
*/
private static void write(DocFile outFile, Writer out, String text) throws DocFileIOException {
@ -331,28 +383,30 @@ public abstract class DocFile {
/**
* Reads from an input stream opened from a given resource into a given buffer.
* If an IOException occurs, it is wrapped in a ResourceIOException.
* If an {@code IOException} occurs, it is wrapped in a {@code ResourceIOException}.
*
* @param docPath the resource for the stream
* @param in the stream
* @param buf the buffer
*
* @param resource the resource for the stream
* @param in the stream
* @param buf the buffer
* @return the number of bytes read, or -1 if at end of file
* @throws ResourceIOException if an exception occurred while reading the stream
*/
private static int readResource(DocPath resource, InputStream in, byte[] buf) throws ResourceIOException {
private static int readResource(DocPath docPath, InputStream in, byte[] buf) throws ResourceIOException {
try {
return in.read(buf);
} catch (IOException e) {
throw new ResourceIOException(resource, e);
throw new ResourceIOException(docPath, e);
}
}
/**
* Reads a line of characters from an input stream opened from a given resource.
* If an IOException occurs, it is wrapped in a ResourceIOException.
* If an {@code IOException} occurs, it is wrapped in a {@code ResourceIOException}.
*
* @param docPath the resource for the stream
* @param in the stream
*
* @param resource the resource for the stream
* @param in the stream
* @return the line of text, or {@code null} if at end of stream
* @throws ResourceIOException if an exception occurred while reading the stream
*/

View File

@ -275,6 +275,9 @@ public class DocPaths {
/** The name of the search javascript file. */
public static final DocPath SEARCH_JS = DocPath.create("search.js");
/** The name of the template for the search javascript file. */
public static final DocPath SEARCH_JS_TEMPLATE = DocPath.create("search.js.template");
/** The name of the file for the serialized form info. */
public static final DocPath SERIALIZED_FORM = DocPath.create("serialized-form.html");

View File

@ -25,7 +25,7 @@
* @test
* @bug 8141492 8071982 8141636 8147890 8166175 8168965 8176794 8175218 8147881
* 8181622 8182263 8074407 8187521 8198522 8182765 8199278 8196201 8196202
* 8184205 8214468 8222548 8223378 8234746 8241219 8254627
* 8184205 8214468 8222548 8223378 8234746 8241219 8254627 8247994
* @summary Test the search feature of javadoc.
* @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@ -711,6 +711,10 @@ public class TestSearch extends JavadocTester {
}
void checkSearchJS() {
// ensure all resource keys were resolved
checkOutput("search.js", false,
"##REPLACE:");
checkOutput("search.js", true,
"function searchIndexWithMatcher(indexArray, matcher, category, nameFunc) {",
"""

View File

@ -23,7 +23,7 @@
/*
* @test
* @bug 8000612 8254627
* @bug 8000612 8254627 8247994
* @summary need test program to validate javadoc resource bundles
* @modules jdk.javadoc/jdk.javadoc.internal.tool
* jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.resources:open
@ -34,6 +34,8 @@
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.tools.*;
import com.sun.tools.classfile.*;
@ -200,6 +202,17 @@ public class CheckResourceKeys {
}
}
// special handling for strings in search.js.template
FileObject fo = fm.getFileForInput(javadocLoc,
"jdk.javadoc.internal.doclets.formats.html",
"resources/search.js.template");
CharSequence search_js = fo.getCharContent(true);
Pattern p = Pattern.compile("##REPLACE:(?<key>[A-Za-z0-9._]+)##");
Matcher m = p.matcher(search_js);
while (m.find()) {
results.add(m.group("key"));
}
// special handling for code strings synthesized in
// jdk.javadoc.internal.doclets.toolkit.util.Utils.getTypeName
String[] extras = {