Javadoc中的char常量显示"常量字段值"页

时间:2014-09-03 00:25:12

标签: java constants javadoc

有没有办法让生成的“常量字段值”页面为char类型常量使用可读字符而不是整数?

例如,如果一个类包含以下常量:

public static final char YES = 'Y';
public static final char NO  = 'N';
public static final char ERROR  = 'E';

我希望javadoc常量字段值页面具有字符表示形式('Y','N','E')而不是整数版本(69,78,89)。

我们有数百个,所以我不想去为每个出现添加一些特定的javadoc注释(例如使用@value)。


更新:感谢SubOptimal的回答,我设法使用我找到ConstantsSummaryWriterImpl writeValue的1.6版源代码来修改private void writeValue(FieldDoc member) { tdAlign("right"); code(); if ("char".equals(member.type().toString())) { print(Util.escapeHtmlChars("'" + ((char) ((Integer)member.constantValue()).intValue()) + "'")); } else { print(Util.escapeHtmlChars(member.constantValueExpression())); } codeEnd(); tdEnd(); } 方法如下:

char

一旦这个类被编译并用于覆盖'tools.jar'中的那个类,{{1}}常量将作为字符输出,而不是数字。

3 个答案:

答案 0 :(得分:2)

你可以通过调整javadoc本身来实现这一点。

  1. 获取javadoc工具的来源(不用担心我们只需要一个文件来调整;-))
    我从这里JDK 7 langtools source
  2. 获取了文件langtools-ce654f4ecfd8.tar.gz
  3. 提取文件ConstantsSummaryWriterImpl.java
  4. 修改方法getValue(FieldDoc member)

    ...
    private Content getValue(FieldDoc member) {
        Content valueContent;
        if ("char".equals(member.type().toString())) {
            valueContent = new StringContent("'" 
                + (char) ((Integer) member.constantValue()).intValue()
                + "'"
            );
        } else {
            valueContent = new StringContent(member.constantValueExpression());
        }
        Content code = HtmlTree.CODE(valueContent);
        return HtmlTree.TD(HtmlStyle.colLast, code);
    }
    ...
    
  5. 编译已更改的文件
    javac -cp ${JAVA_HOME}/lib/tools.jar -d . ConstantsSummaryWriterImpl.java

  6. 运行javadoc
    javadoc -J-Xbootclasspath/p:.;${JAVA_HOME}/lib/tools.jar -d api/ Scratch.java

  7. 文件 Scratch.java

    public class Scratch {
        public static final char YES = 'Y';
        public static final char NO  = 'N';
        public static final char ERROR  = 'E';
    }
    

答案 1 :(得分:0)

无法完成。不幸的是,javadoc在这方面有点密集 - char数字原语。

您可以使用字符串

来解决它
public static final String YES = "Y";
public static final String NO  = "N";
public static final String ERROR  = "E";

并重构您的代码以使用您之前使用char常量的实用程序方法:

public static char asChar(String str) {
    if (str.length() != 1) {
         throw new IllegalArgumentException(str + " must be exactly 1 character long");
    }
    return str.charAt(0);
}

例如

if (ch == asChar(ERROR))

希望这可以让人忍受。

请注意参数检查,以确保您不会意外地声明其中一个字符串而不是单个字符。

答案 2 :(得分:0)

某些后期处理是否可行?

该程序遍历文件树并处理所有名为constant-values.html的文件。它们使用Jericho HTML Parser加载。检查名为constantValuesContainer的表:如果第一列包含文本static final char,并且最后一列中的值是整数值,则将其替换为相应的字符。

请注意,这只是一个草图(但至少在"它自己" JavaDoc ;-)上进行了测试)。替换的条件可以改进。例如,第一列中文本的匹配应该更加健壮(对于有人创建以char开头的类的情况....)。只有当整数值是有效的 ASCII 字符时,才应该进行替换,以避免弄乱像static final char CHAR_MAX = 0xFFFF这样的常量。但是这样的调整应该很容易,如果(!)这样的后处理步骤是可行的方法。

import static java.nio.file.FileVisitResult.CONTINUE;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.OutputDocument;
import net.htmlparser.jericho.Segment;
import net.htmlparser.jericho.Source;

public class ConstantsTest
{
    private static final char CHAR_A = 'A';
    protected static final char CHAR_B = 'B';
    static final char CHAR_C = 'C';
    public static final char CHAR_D = 'D';
    public static final char CHAR_E = 'E';
    public static final char CHAR_F = 'F';
    public static final int INT_65 = 65;

    public static void main(String[] args) throws MalformedURLException, IOException
    {
        Path path = FileSystems.getDefault().getPath("./doc/");
        Files.walkFileTree(path, new FileProcessor());
    }

    static class FileProcessor extends SimpleFileVisitor<Path>
    {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attributes)
        {
            //System.out.println("Visit "+file+" name '"+file.getFileName()+"'");
            if (file.getFileName().toString().equals("constant-values.html"))
            {
                process(file);
            }
            return CONTINUE;
        }
    }

    private static void process(Path file) 
    {
        try
        {
            doProcess(file);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    private static void doProcess(Path file) throws IOException
    {
        System.out.println("Processing "+file);
        Source source=new Source(file.toFile());
        OutputDocument outputDocument=new OutputDocument(source);
        for (Element element : source.getAllElementsByClass("constantValuesContainer"))
        {
            List<Element> colFirsts = element.getAllElementsByClass("colFirst");
            List<Element> colLasts = element.getAllElementsByClass("colLast");
            for (int i=0; i<colFirsts.size(); i++)
            {
                Element colFirst = colFirsts.get(i);
                Segment colFirstContent = colFirst.getContent();
                String colFirstText = colFirstContent.getTextExtractor().toString();

                // TODO Generalize this according to your needs,
                // maybe with some RegEx...
                if (colFirstText.contains("static final char"))
                {
                    Element colLast = colLasts.get(i);
                    List<Element> children = colLast.getAllElements("code");
                    if (children.size() == 1)
                    {
                        Element child = children.get(0);
                        Segment childContent = child.getContent();
                        String childText = childContent.getTextExtractor().toString();
                        try
                        {
                            int value = Integer.parseInt(childText);
                            outputDocument.replace(childContent, String.valueOf((char)value));
                        }
                        catch (NumberFormatException e)
                        {
                            System.out.println("Value is not a number: "+childText+", ignoring");
                        }
                    }
                }
            }
        }
        outputDocument.writeTo(
            new OutputStreamWriter(new FileOutputStream(file.toFile())));
        System.out.println("Processing "+file+" DONE");
    }


}