# HG changeset patch # User jjg # Date 1352241169 28800 # Node ID 6f87132c2e54859938eddfcd9c9b81f0f003806a # Parent 88145bb2ddcdf05ebdd543fb4ab92662e0f0b5d4 8000612: Discrepancy between resources provided in javadoc resource files and resources required by code Reviewed-by: bpatel diff -r 88145bb2ddcd -r 6f87132c2e54 langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties Tue Nov 06 14:45:27 2012 +0000 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties Tue Nov 06 14:32:49 2012 -0800 @@ -41,32 +41,21 @@ doclet.Help=Help doclet.Skip_navigation_links=Skip navigation links doclet.New_Page=NewPage -doclet.None=None -doclet.Factory_Method_Detail=Static Factory Method Detail doclet.navDeprecated=Deprecated -doclet.Deprecated_List=Deprecated List doclet.Window_Deprecated_List=Deprecated List -doclet.Note_0_is_deprecated=Note: {0} is deprecated. doclet.Overrides=Overrides: doclet.in_class=in class -doclet.0_Fields_and_Methods="{0}" Fields and Methods -doclet.Index_of_Fields_and_Methods=Index of Fields and Methods doclet.Static_variable_in=Static variable in {0} doclet.Variable_in=Variable in {0} doclet.Constructor_for=Constructor for {0} doclet.Static_method_in=Static method in {0} doclet.Method_in=Method in {0} -doclet.throws=throws doclet.package=package doclet.MalformedURL=Malformed URL: {0} doclet.File_error=Error reading file: {0} doclet.URL_error=Error fetching URL: {0} -doclet.No_Package_Comment_File=For Package {0} Package.Comment file not found -doclet.No_Source_For_Class=Source information for class {0} not available. doclet.see.class_or_package_not_found=Tag {0}: reference not found: {1} doclet.see.class_or_package_not_accessible=Tag {0}: reference not accessible: {1} -doclet.see.malformed_tag=Tag {0}: Malformed: {1} -doclet.Inherited_API_Summary=Inherited API Summary doclet.Deprecated_API=Deprecated API doclet.Deprecated_Packages=Deprecated Packages doclet.Deprecated_Classes=Deprecated Classes @@ -92,10 +81,7 @@ doclet.deprecated_methods=deprecated methods doclet.deprecated_enum_constants=deprecated enum constants doclet.deprecated_annotation_type_members=deprecated annotation type elements -doclet.Frame_Output=Frame Output -doclet.Docs_generated_by_Javadoc=Documentation generated by Javadoc. doclet.Generated_Docs_Untitled=Generated Documentation (Untitled) -doclet.Blank=Blank doclet.Other_Packages=Other Packages doclet.Package_Description=Package {0} Description doclet.Description=Description @@ -105,32 +91,24 @@ doclet.Subinterfaces=All Known Subinterfaces: doclet.Implementing_Classes=All Known Implementing Classes: doclet.also=also -doclet.Option=Option -doclet.Or=Or +doclet.FRAMES=FRAMES doclet.Frames=Frames +doclet.NO_FRAMES=NO FRAMES doclet.No_Frames=No Frames doclet.Package_Hierarchies=Package Hierarchies: doclet.Hierarchy_For_Package=Hierarchy For Package {0} -doclet.Source_Code=Source Code: doclet.Hierarchy_For_All_Packages=Hierarchy For All Packages -doclet.Cannot_handle_no_packages=Cannot handle no packages. doclet.Frame_Alert=Frame Alert -doclet.Overview-Member-Frame=Overview Member Frame doclet.Frame_Warning_Message=This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to {0}. doclet.No_Script_Message=JavaScript is disabled on your browser. doclet.Non_Frame_Version=Non-frame version -doclet.Frame_Version=Frame version -doclet.Following_From_Class=Following copied from class: {0} -doclet.Following_From_Interface=Following copied from interface: {0} doclet.Description_From_Interface=Description copied from interface: doclet.Description_From_Class=Description copied from class: -doclet.Standard_doclet_invoked=Standard doclet invoked... doclet.No_Non_Deprecated_Classes_To_Document=No non-deprecated classes found to document. doclet.Interfaces_Italic=Interfaces (italic) doclet.Enclosing_Class=Enclosing class: doclet.Enclosing_Interface=Enclosing interface: doclet.Window_Source_title=Source code -doclet.Help_title=API Help doclet.Window_Help_title=API Help doclet.Help_line_1=How This API Document Is Organized doclet.Help_line_2=This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows. @@ -168,19 +146,6 @@ doclet.Help_annotation_type_line_1=Each annotation type has its own separate page with the following sections: doclet.Help_annotation_type_line_2=Annotation Type declaration doclet.Help_annotation_type_line_3=Annotation Type description -doclet.Style_line_1=Javadoc style sheet -doclet.Style_line_2=Define colors, fonts and other style attributes here to override the defaults -doclet.Style_line_3=Page background color -doclet.Style_Headings=Headings -doclet.Style_line_4=Table colors -doclet.Style_line_5=Dark mauve -doclet.Style_line_6=Light mauve -doclet.Style_line_7=White -doclet.Style_line_8=Font used in left-hand frame lists -doclet.Style_line_9=Example of smaller, sans-serif font in frames -doclet.Style_line_10=Navigation bar fonts and colors -doclet.Style_line_11=Dark Blue -doclet.Style_line_12=Table caption style doclet.ClassUse_Packages.that.use.0=Packages that use {0} doclet.ClassUse_Uses.of.0.in.1=Uses of {0} in {1} doclet.ClassUse_Classes.in.0.used.by.1=Classes in {0} used by {1} @@ -210,12 +175,9 @@ doclet.Window_ClassUse_Header=Uses of {0} {1} doclet.ClassUse_Title=Uses of {0}
{1} doclet.navClassUse=Use -doclet.link_option_twice=Extern URL link option (link or linkoffline) used twice. doclet.Error_in_packagelist=Error in using -group option: {0} {1} doclet.Groupname_already_used=In -group option, groupname already used: {0} doclet.Same_package_name_used=Package name format used twice: {0} -doclet.Serialization.Excluded_Class=Non-transient field {1} uses excluded class {0}. -doclet.Serialization.Nonexcluded_Class=Non-transient field {1} uses hidden, non-included class {0}. doclet.exception_encountered=Exception encountered while processing {1}\n{0} doclet.usage=Provided by Standard doclet:\n\ -d Destination directory for output files\n\ diff -r 88145bb2ddcd -r 6f87132c2e54 langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties Tue Nov 06 14:45:27 2012 +0000 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties Tue Nov 06 14:32:49 2012 -0800 @@ -21,10 +21,8 @@ doclet.Copying_File_0_To_File_1=Copying file {0} to file {1}... doclet.No_Public_Classes_To_Document=No public or protected classes found to document. doclet.Unable_to_create_directory_0=Unable to create directory {0} -doclet.destination_directory_not_found_0=Destination directory not found {0} doclet.destination_directory_not_directory_0=Destination directory is not a directory {0} doclet.destination_directory_not_writable_0=Destination directory not writable {0} -doclet.Error_creating_tmp_file=Error creating temporary file, using default platform encoding. doclet.Encoding_not_supported=Encoding not supported: {0} doclet.Building_Tree=Building tree for all the packages and classes... doclet.Building_Index=Building index for all the packages and classes... @@ -74,7 +72,6 @@ doclet.Enum_Constant_Summary=Enum Constant Summary doclet.Constructor_Summary=Constructor Summary doclet.Method_Summary=Method Summary -doclet.Factory_Method_Summary=Static Factory Method Summary doclet.Interfaces=Interfaces doclet.Enums=Enums doclet.AnnotationTypes=Annotation Types @@ -88,7 +85,6 @@ doclet.All_Implemented_Interfaces=All Implemented Interfaces: doclet.All_classes_and_interfaces=All classes and interfaces (except non-static nested types) doclet.Package_class_and_interface_descriptions=Package, class and interface descriptions -doclet.Members=Members doclet.Interface=Interface doclet.Class=Class doclet.AnnotationType=Annotation Type @@ -107,18 +103,13 @@ doclet.Exception=Exception doclet.exception=exception doclet.exceptions=exceptions -doclet.extended_by=extended by -doclet.extends=extends doclet.Package_private=(package private) -doclet.implements=implementsdoclet.Same_package_name_used=Package name format used twice: {0} doclet.Nested_Classes_Interfaces_Inherited_From_Class=Nested classes/interfaces inherited from class doclet.Nested_Classes_Interface_Inherited_From_Interface=Nested classes/interfaces inherited from interface doclet.Methods_Inherited_From_Class=Methods inherited from class doclet.Methods_Inherited_From_Interface=Methods inherited from interface doclet.Fields_Inherited_From_Class=Fields inherited from class doclet.Fields_Inherited_From_Interface=Fields inherited from interface -doclet.Serializable=Serializable -doclet.Externalizable=Externalizable doclet.Annotation_Type_Member_Detail=Element Detail doclet.Enum_Constant_Detail=Enum Constant Detail doclet.Constants_Summary=Constant Field Values @@ -126,7 +117,6 @@ doclet.Method_Detail=Method Detail doclet.Constructor_Detail=Constructor Detail doclet.Deprecated=Deprecated. -doclet.Deprecated_class=This class is deprecated. doclet.Groupname_already_used=In -group option, groupname already used: {0} doclet.value_tag_invalid_reference={0} (referenced by @value tag) is an unknown reference. doclet.value_tag_invalid_constant=@value tag (which references {0}) can only be used in constants. diff -r 88145bb2ddcd -r 6f87132c2e54 langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Tue Nov 06 14:45:27 2012 +0000 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Tue Nov 06 14:32:49 2012 -0800 @@ -555,7 +555,7 @@ * * @param cd the ClassDoc to check. * @param lowerCaseOnly true if you want the name returned in lower case. - * If false, the first letter of the name is capatilized. + * If false, the first letter of the name is capitalized. * @return */ public static String getTypeName(Configuration config, diff -r 88145bb2ddcd -r 6f87132c2e54 langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java --- a/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java Tue Nov 06 14:45:27 2012 +0000 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java Tue Nov 06 14:32:49 2012 -0800 @@ -267,8 +267,6 @@ } if (referencedClass == null) { /* may just not be in this run */ -// docenv().warning(holder, "tag.see.class_not_found", -// where, text); // check if it's a package name referencedPackage = docenv().lookupPackage(where); return; diff -r 88145bb2ddcd -r 6f87132c2e54 langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties --- a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties Tue Nov 06 14:45:27 2012 +0000 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties Tue Nov 06 14:32:49 2012 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2012, 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 @@ -64,7 +64,6 @@ main.incompatible.access.flags=More than one of -public, -private, -package, or -protected specified. main.cant.read=cannot read {0} main.Loading_source_files_for_package=Loading source files for package {0}... -main.Loading_source_file_for_class=Loading source file for class {0}... main.Loading_source_file=Loading source file {0}... main.Building_tree=Constructing Javadoc information... main.no_source_files_for_package=No source files for package {0} @@ -96,13 +95,12 @@ tag.see.can_not_find_member=Tag {0}: can''t find {1} in {2} tag.see.no_close_bracket_on_url=Tag {0}: missing final ''>'': "{1}" tag.see.no_close_quote=Tag {0}: no final close quote: "{1}" -tag.see.class_not_found=class {0} not found for @see tag: "{1}" tag.see.class_not_specified=Tag {0}: class not specified: "{1}" tag.see.illegal_character=Tag {0}:illegal character: "{1}" in "{2}" tag.see.malformed_see_tag=Tag {0}: malformed: "{1}" -tag.throws.exception_not_found={0} tag, class {1} not found. tag.End_delimiter_missing_for_possible_SeeTag=End Delimiter } missing for possible See Tag in comment string: "{0}" tag.Improper_Use_Of_Link_Tag=Missing closing ''}'' character for inline tag: "{0}" +tag.serialField.illegal_character=illegal character {0} in @serialField tag: {1}. javadoc.File_Read_Error=Error while reading file {0} javadoc.Body_missing_from_html_file=Body tag missing from HTML file javadoc.End_body_missing_from_html_file=Close body tag missing from HTML file @@ -110,4 +108,3 @@ javadoc.class_not_found=Class {0} not found. javadoc.error=error javadoc.warning=warning -tag.serialField.illegal_character=illegal character {0} in @serialField tag: {1}. diff -r 88145bb2ddcd -r 6f87132c2e54 langtools/test/tools/javac/diags/CheckResourceKeys.java --- a/langtools/test/tools/javac/diags/CheckResourceKeys.java Tue Nov 06 14:45:27 2012 +0000 +++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java Tue Nov 06 14:32:49 2012 -0800 @@ -310,9 +310,9 @@ pkg, EnumSet.of(JavaFileObject.Kind.CLASS), true)) { String name = fo.getName(); // ignore resource files, and files which are not really part of javac - if (name.contains("resources") - || name.contains("Launcher.class") - || name.contains("CreateSymbols.class")) + if (name.matches(".*resources.[A-Za-z_0-9]+\\.class") + || name.endsWith("Launcher.class") + || name.endsWith("CreateSymbols.class")) continue; scan(fo, results); } diff -r 88145bb2ddcd -r 6f87132c2e54 langtools/test/tools/javadoc/CheckResourceKeys.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javadoc/CheckResourceKeys.java Tue Nov 06 14:32:49 2012 -0800 @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2010, 2012, 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 8000612 + * @summary need test program to validate javadoc resource bundles + */ + +import java.io.*; +import java.util.*; +import javax.tools.*; +import com.sun.tools.classfile.*; + +/** + * Compare string constants in javadoc classes against keys in javadoc resource bundles. + */ +public class CheckResourceKeys { + /** + * Main program. + * Options: + * -finddeadkeys + * look for keys in resource bundles that are no longer required + * -findmissingkeys + * look for keys in resource bundles that are missing + * + * @throws Exception if invoked by jtreg and errors occur + */ + public static void main(String... args) throws Exception { + CheckResourceKeys c = new CheckResourceKeys(); + if (c.run(args)) + return; + + if (is_jtreg()) + throw new Exception(c.errors + " errors occurred"); + else + System.exit(1); + } + + static boolean is_jtreg() { + return (System.getProperty("test.src") != null); + } + + /** + * Main entry point. + */ + boolean run(String... args) throws Exception { + boolean findDeadKeys = false; + boolean findMissingKeys = false; + + if (args.length == 0) { + if (is_jtreg()) { + findDeadKeys = true; + findMissingKeys = true; + } else { + System.err.println("Usage: java CheckResourceKeys "); + System.err.println("where options include"); + System.err.println(" -finddeadkeys find keys in resource bundles which are no longer required"); + System.err.println(" -findmissingkeys find keys in resource bundles that are required but missing"); + return true; + } + } else { + for (String arg: args) { + if (arg.equalsIgnoreCase("-finddeadkeys")) + findDeadKeys = true; + else if (arg.equalsIgnoreCase("-findmissingkeys")) + findMissingKeys = true; + else + error("bad option: " + arg); + } + } + + if (errors > 0) + return false; + + Set codeKeys = getCodeKeys(); + Set resourceKeys = getResourceKeys(); + + System.err.println("found " + codeKeys.size() + " keys in code"); + System.err.println("found " + resourceKeys.size() + " keys in resource bundles"); + + if (findDeadKeys) + findDeadKeys(codeKeys, resourceKeys); + + if (findMissingKeys) + findMissingKeys(codeKeys, resourceKeys); + + return (errors == 0); + } + + /** + * Find keys in resource bundles which are probably no longer required. + * A key is required if there is a string in the code that is a resource key, + * or if the key is well-known according to various pragmatic rules. + */ + void findDeadKeys(Set codeKeys, Set resourceKeys) { + for (String rk: resourceKeys) { + if (codeKeys.contains(rk)) + continue; + + error("Resource key not found in code: " + rk); + } + } + + /** + * For all strings in the code that look like they might be + * a resource key, verify that a key exists. + */ + void findMissingKeys(Set codeKeys, Set resourceKeys) { + for (String ck: codeKeys) { + if (resourceKeys.contains(ck)) + continue; + error("No resource for \"" + ck + "\""); + } + } + + /** + * Get the set of strings from (most of) the javadoc classfiles. + */ + Set getCodeKeys() throws IOException { + Set results = new TreeSet(); + JavaCompiler c = ToolProvider.getSystemJavaCompiler(); + JavaFileManager fm = c.getStandardFileManager(null, null, null); + JavaFileManager.Location javadocLoc = findJavadocLocation(fm); + String[] pkgs = { + "com.sun.tools.doclets", + "com.sun.tools.javadoc" + }; + for (String pkg: pkgs) { + for (JavaFileObject fo: fm.list(javadocLoc, + pkg, EnumSet.of(JavaFileObject.Kind.CLASS), true)) { + String name = fo.getName(); + // ignore resource files + if (name.matches(".*resources.[A-Za-z_0-9]+\\.class")) + continue; + scan(fo, results); + } + } + + // special handling for code strings synthesized in + // com.sun.tools.doclets.internal.toolkit.util.Util.getTypeName + String[] extras = { + "AnnotationType", "Class", "Enum", "Error", "Exception", "Interface" + }; + for (String s: extras) { + if (results.contains("doclet." + s)) + results.add("doclet." + s.toLowerCase()); + } + + return results; + } + + // depending on how the test is run, javadoc may be on bootclasspath or classpath + JavaFileManager.Location findJavadocLocation(JavaFileManager fm) { + JavaFileManager.Location[] locns = + { StandardLocation.PLATFORM_CLASS_PATH, StandardLocation.CLASS_PATH }; + try { + for (JavaFileManager.Location l: locns) { + JavaFileObject fo = fm.getJavaFileForInput(l, + "com.sun.tools.javadoc.Main", JavaFileObject.Kind.CLASS); + if (fo != null) { + System.err.println("found javadoc in " + l); + return l; + } + } + } catch (IOException e) { + throw new Error(e); + } + throw new IllegalStateException("Cannot find javadoc"); + } + + /** + * Get the set of strings from a class file. + * Only strings that look like they might be a resource key are returned. + */ + void scan(JavaFileObject fo, Set results) throws IOException { + //System.err.println("scan " + fo.getName()); + InputStream in = fo.openInputStream(); + try { + ClassFile cf = ClassFile.read(in); + for (ConstantPool.CPInfo cpinfo: cf.constant_pool.entries()) { + if (cpinfo.getTag() == ConstantPool.CONSTANT_Utf8) { + String v = ((ConstantPool.CONSTANT_Utf8_info) cpinfo).value; + if (v.matches("(doclet|main|javadoc|tag)\\.[A-Za-z0-9-_.]+")) + results.add(v); + } + } + } catch (ConstantPoolException ignore) { + } finally { + in.close(); + } + } + + /** + * Get the set of keys from the javadoc resource bundles. + */ + Set getResourceKeys() { + String[] names = { + "com.sun.tools.doclets.formats.html.resources.standard", + "com.sun.tools.doclets.internal.toolkit.resources.doclets", + "com.sun.tools.javadoc.resources.javadoc", + }; + Set results = new TreeSet(); + for (String name : names) { + ResourceBundle b = ResourceBundle.getBundle(name); + results.addAll(b.keySet()); + } + return results; + } + + /** + * Report an error. + */ + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; +}