001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2016 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.doclets; 021 022import java.io.FileNotFoundException; 023import java.io.FileOutputStream; 024import java.io.OutputStreamWriter; 025import java.io.PrintWriter; 026import java.io.Writer; 027import java.nio.charset.StandardCharsets; 028 029import com.sun.javadoc.ClassDoc; 030import com.sun.javadoc.DocErrorReporter; 031import com.sun.javadoc.FieldDoc; 032import com.sun.javadoc.RootDoc; 033 034/** 035 * Doclet which is used to write property file with short descriptions 036 * (first sentences) of TokenTypes' constants. 037 * Request: 724871 038 * For ide plugins (like the eclipse plugin) it would be useful to have 039 * programmatic access to the first sentence of the TokenType constants, 040 * so they can use them in their configuration gui. 041 * @author o_sukhodolsky 042 */ 043public final class TokenTypesDoclet { 044 /** Command line option to specify file to write output of the doclet. */ 045 private static final String DEST_FILE_OPT = "-destfile"; 046 047 /** Stop instances being created. */ 048 private TokenTypesDoclet() { 049 } 050 051 /** 052 * The doclet's starter method. 053 * @param root {@code RootDoc} given to the doclet 054 * @return true if the given {@code RootDoc} is processed. 055 * @exception FileNotFoundException will be thrown if the doclet 056 * will be unable to write to the specified file. 057 */ 058 public static boolean start(RootDoc root) 059 throws FileNotFoundException { 060 final String fileName = getDestFileName(root.options()); 061 final FileOutputStream fos = new FileOutputStream(fileName); 062 final Writer osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); 063 final PrintWriter writer = new PrintWriter(osw, false); 064 065 try { 066 final ClassDoc[] classes = root.classes(); 067 final FieldDoc[] fields = classes[0].fields(); 068 for (final FieldDoc field : fields) { 069 if (field.isStatic() && field.isPublic() && field.isFinal() 070 && "int".equals(field.type().qualifiedTypeName())) { 071 if (field.firstSentenceTags().length != 1) { 072 final String message = "Should be only one tag."; 073 throw new IllegalArgumentException(message); 074 } 075 writer.println(field.name() + "=" 076 + field.firstSentenceTags()[0].text()); 077 } 078 } 079 } 080 finally { 081 writer.close(); 082 } 083 084 return true; 085 } 086 087 /** 088 * Returns option length (how many parts are in option). 089 * @param option option name to process 090 * @return option length (how many parts are in option). 091 */ 092 public static int optionLength(String option) { 093 if (DEST_FILE_OPT.equals(option)) { 094 return 2; 095 } 096 return 0; 097 } 098 099 /** 100 * Checks that only valid options was specified. 101 * @param options all parsed options 102 * @param reporter the reporter to report errors. 103 * @return true if only valid options was specified 104 */ 105 public static boolean checkOptions(String[][] options, DocErrorReporter reporter) { 106 boolean foundDestFileOption = false; 107 for (final String[] opt : options) { 108 if (DEST_FILE_OPT.equals(opt[0])) { 109 if (foundDestFileOption) { 110 reporter.printError("Only one -destfile option allowed."); 111 return false; 112 } 113 foundDestFileOption = true; 114 } 115 } 116 if (!foundDestFileOption) { 117 final String message = 118 "Usage: javadoc -destfile file -doclet TokenTypesDoclet ..."; 119 reporter.printError(message); 120 } 121 return foundDestFileOption; 122 } 123 124 /** 125 * Reads destination file name. 126 * @param options all specified options. 127 * @return destination file name 128 */ 129 private static String getDestFileName(String[]... options) { 130 String fileName = null; 131 for (final String[] opt : options) { 132 if (DEST_FILE_OPT.equals(opt[0])) { 133 fileName = opt[1]; 134 } 135 } 136 return fileName; 137 } 138}