📄 checknamesprocessor.java
字号:
/* * @(#)CheckNamesProcessor.java 1.2 06/09/28 * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. */import java.util.Set;import java.util.EnumSet;import javax.annotation.processing.*;import javax.lang.model.SourceVersion;import javax.lang.model.element.*;import javax.lang.model.type.*;import javax.lang.model.util.*;import static javax.lang.model.SourceVersion.*;import static javax.lang.model.element.Modifier.*;import static javax.lang.model.element.ElementKind.*;import static javax.lang.model.type.TypeKind.*;import static javax.lang.model.util.ElementFilter.*;import static javax.tools.Diagnostic.Kind.*;/** * A sample processor to check naming conventions are being followed. * * <h3>How to run this processor from the command line</h3> * <ol> * <li> Compile this file; for example<br> * {@code javac -d procdir CheckNamesProcessor.java} * <li> Use {@code javac} to run the annotation processor on itself:<br> * {@code javac -processorpath procdir -processor CheckNamesProcessor -proc:only CheckNamesProcessor.java} * </ol> * * <h3>Another way to run this processor from the command line</h3> * <ol> * <li> Compile the processor as before * * <li> Create a UTF-8 encoded text file named {@code * javax.annotation.processing.Processor} in the {@code * META-INF/services} directory. The contents of the file are a list * of the binary names of the concrete processor classes, one per * line. This provider-configuration file is used by {@linkplain * java.util.ServiceLoader service-loader} style lookup. * * <li> Create a {@code jar} file with the processor classes and * {@code META-INF} information. * * <li> Such a {@code jar} file can now be used with the <i>discovery * process</i> without explicitly naming the processor to run:<br> * {@code javac -processorpath procdir -proc:only CheckNamesProcessor.java} * * </ol> * * For some notes on how to run an annotation processor inside * NetBeans, see http://wiki.java.net/bin/view/Netbeans/FaqApt. * * <h3>Possible Enhancements</h3> * <ul> * * <li> Support an annotation processor option to control checking * exported API elements ({@code public} and {@code protected} ones) * or all elements * * <li> Print out warnings that are more informative * * <li> Return a true/false status if any warnings were printed or * compute and return name warning count * * <li> Implement checks of package names * * <li> Use the Tree API, com.sun.source, to examine names within method bodies * * <li> Define an annotation type whose presence can indicate a * different naming convention is being followed * * <li> Implement customized checks on elements in chosen packages * * </ul> * * @author Joseph D. Darcy */@SupportedAnnotationTypes("*") // Process (check) everythingpublic class CheckNamesProcessor extends AbstractProcessor { private NameChecker nameChecker; /** * Check that the names of the root elements (and their enclosed * elements) follow the appropriate naming conventions. This * processor examines all files regardless of whether or not * annotations are present; no new source or class files are * generated. * * <p>Processors that actually process specific annotations should * <em>not</em> report supporting {@code *}; this could cause * performance degradations and other undesirable outcomes. */ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { if (!roundEnv.processingOver()) { for (Element element : roundEnv.getRootElements() ) nameChecker.checkNames(element); } return false; // Allow other processors to examine files too. } @Override public void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); nameChecker = new NameChecker(processingEnv); } @Override public SourceVersion getSupportedSourceVersion() { /* * Return latest source version instead of a fixed version * like RELEASE_6. To return a fixed version, this class * could be annotated with a SupportedSourceVersion * annotation. * * Warnings will be issued if any unknown language constructs * are encountered. */ return SourceVersion.latest(); } /** * Provide checks that an element and its enclosed elements follow * the usual naming conventions. * * <p> Conventions from JLSv3 section 6.8: * * <ul> * <li> Classes and interfaces: camel case, first letter is uppercase * <li> Methods: camel case, first letter is lowercase * <li> Type variables: one uppercase letter * <li> Fields * <ul> * <li> non-final: camel case, initial lowercase * <li> constant: uppercase separated by underscores * </ul> * <li> Packages: checks left as exercise for the reader, see JLSv3 section 7.7 * </ul> */ private static class NameChecker { private final Messager messager; private final Types typeUtils; NameCheckScanner nameCheckScanner = new NameCheckScanner(); NameChecker(ProcessingEnvironment processsingEnv) { this.messager = processsingEnv.getMessager(); this.typeUtils = processsingEnv.getTypeUtils(); } /** * If the name of the argument or its enclosed elements * violates the naming conventions, report a warning. */ public void checkNames(Element element) { // Implement name checks with a visitor, but expose that // functionality through this method instead. nameCheckScanner.scan(element); } /** * Visitor to implement name checks. */ private class NameCheckScanner extends ElementScanner6<Void, Void> { // The visitor could be enhanced to return true/false if // there were warnings reported or a count of the number // of warnings. This could be facilitated by using // Boolean or Integer instead of Void for the actual type // arguments. In more detail, one way to tally the number // of warnings would be for each method to return the sum // of the warnings it and the methods it called issued, a // bottom-up computation. In that case, the first type // argument would be Integer and the second type argument // would still be Void. Alternatively, the current count // could be passed along in Integer parameter p and each // method could return the Integer sum of p and the // warnings the method issued. Some computations are more // naturally expressed in one form instead of the other. // If greater control is needed over traversal order, a // SimpleElementVisitor can be extended instead of an // ElementScanner. /** * Check the name of a type and its enclosed elements and * type parameters. */ @Override public Void visitType(TypeElement e, Void p) { scan(e.getTypeParameters(), p); // Check the names of any type parameters checkCamelCase(e, true); // Check the name of the class or interface super.visitType(e, p); // Check the names of any enclosed elements return null; } /** * Check the name of an executable (method, constructor, * etc.) and its type parameters. */ @Override public Void visitExecutable(ExecutableElement e, Void p) { scan(e.getTypeParameters(), p); // Check the names of any type parameters // Check the name of the executable if (e.getKind() == METHOD) { // Make sure that a method does not have the same // name as its class or interface. Name name = e.getSimpleName(); if (name.contentEquals(e.getEnclosingElement().getSimpleName())) messager.printMessage(WARNING, "A method should not have the same name as its enclosing type, ``" + name + "''." , e); checkCamelCase(e, false); } // else constructors and initializers don't have user-defined names // At this point, could use the Tree API, // com.sun.source, to examine the names of entities // inside a method. super.visitExecutable(e, p); return null; } /** * Check the name of a field, parameter, etc. */ @Override public Void visitVariable(VariableElement e, Void p) { if (!checkForSerial(e)) { // serialVersionUID checks // Is the variable a constant? if (e.getKind() == ENUM_CONSTANT || e.getConstantValue() != null ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -