001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2014 Oliver Burn 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//////////////////////////////////////////////////////////////////////////////// 019package com.puppycrawl.tools.checkstyle.doclets; 020 021import java.io.FileNotFoundException; 022import java.io.FileOutputStream; 023import java.io.PrintStream; 024 025import com.sun.javadoc.ClassDoc; 026import com.sun.javadoc.DocErrorReporter; 027import com.sun.javadoc.FieldDoc; 028import com.sun.javadoc.RootDoc; 029 030/** 031 * Doclet which is used to write property file with short descriptions 032 * (first sentences) of TokenTypes' constants. 033 * Request: 724871 034 * For ide plugins (like the eclipse plugin) it would be useful to have 035 * programmatic access to the first sentence of the TokenType constants, 036 * so they can use them in their configuration gui. 037 * @author o_sukhodolsky 038 */ 039public final class TokenTypesDoclet 040{ 041 /** Command line option to specify file to write output of the doclet. */ 042 private static final String DEST_FILE_OPT = "-destfile"; 043 044 /** Stop instances being created. */ 045 private TokenTypesDoclet() 046 { 047 } 048 049 /** 050 * The doclet's starter method. 051 * @param root <code>RootDoc</code> given to the doclet 052 * @exception FileNotFoundException will be thrown if the doclet 053 * will be unable to write to the specified file. 054 * @return true if the given <code>RootDoc</code> is processed. 055 */ 056 public static boolean start(RootDoc root) throws FileNotFoundException 057 { 058 final String fileName = getDestFileName(root.options()); 059 final FileOutputStream fos = new FileOutputStream(fileName); 060 PrintStream ps = null; 061 try { 062 ps = new PrintStream(fos); 063 final ClassDoc[] classes = root.classes(); 064 if ((classes.length != 1) 065 || !"TokenTypes".equals(classes[0].name())) 066 { 067 final String message = 068 "The doclet should be used for TokenTypes only"; 069 throw new IllegalArgumentException(message); 070 } 071 072 final FieldDoc[] fields = classes[0].fields(); 073 for (final FieldDoc field : fields) { 074 if (field.isStatic() && field.isPublic() && field.isFinal() 075 && "int".equals((field.type().qualifiedTypeName()))) 076 { 077 if (field.firstSentenceTags().length != 1) { 078 final String message = "Should be only one tag."; 079 throw new IllegalArgumentException(message); 080 } 081 ps.println(field.name() + "=" 082 + field.firstSentenceTags()[0].text()); 083 } 084 } 085 } 086 finally { 087 if (ps != null) { 088 ps.close(); 089 } 090 } 091 092 return true; 093 } 094 095 /** 096 * Returns option length (how many parts are in option). 097 * @param option option name to process 098 * @return option length (how many parts are in option). 099 */ 100 public static int optionLength(String option) 101 { 102 if (DEST_FILE_OPT.equals(option)) { 103 return 2; 104 } 105 return 0; 106 } 107 108 /** 109 * Checks that only valid options was specified. 110 * @param options all parsed options 111 * @param reporter the reporter to report errors. 112 * @return true if only valid options was specified 113 */ 114 public static boolean validOptions(String[][] options, 115 DocErrorReporter reporter) 116 { 117 boolean foundDestFileOption = false; 118 for (final String[] opt : options) { 119 if (DEST_FILE_OPT.equals(opt[0])) { 120 if (foundDestFileOption) { 121 reporter.printError("Only one -destfile option allowed."); 122 return false; 123 } 124 foundDestFileOption = true; 125 } 126 } 127 if (!foundDestFileOption) { 128 final String message = 129 "Usage: javadoc -destfile file -doclet TokenTypesDoclet ..."; 130 reporter.printError(message); 131 } 132 return foundDestFileOption; 133 } 134 135 /** 136 * Reads destination file name. 137 * @param options all specified options. 138 * @return destination file name 139 */ 140 private static String getDestFileName(String[][] options) 141 { 142 String fileName = null; 143 for (final String[] opt : options) { 144 if (DEST_FILE_OPT.equals(opt[0])) { 145 fileName = opt[1]; 146 } 147 } 148 return fileName; 149 } 150}