1 package com.puppycrawl.tools.checkstyle.checks.design; 20 21 import com.puppycrawl.tools.checkstyle.api.Check; 22 import com.puppycrawl.tools.checkstyle.api.DetailAST; 23 import com.puppycrawl.tools.checkstyle.api.TokenTypes; 24 import com.puppycrawl.tools.checkstyle.api.ScopeUtils; 25 26 import java.util.Stack ; 27 28 41 public class FinalClassCheck 42 extends Check 43 { 44 45 private final Stack mClasses = new Stack (); 46 47 48 public int[] getDefaultTokens() 49 { 50 return new int[]{TokenTypes.CLASS_DEF, TokenTypes.CTOR_DEF}; 51 } 52 53 54 public void visitToken(DetailAST aAST) 55 { 56 final DetailAST modifiers = aAST.findFirstToken(TokenTypes.MODIFIERS); 57 58 if (aAST.getType() == TokenTypes.CLASS_DEF) { 59 final boolean isFinal = (modifiers != null) 60 && modifiers.branchContains(TokenTypes.FINAL); 61 final boolean isAbstract = (modifiers != null) 62 && modifiers.branchContains(TokenTypes.ABSTRACT); 63 mClasses.push(new ClassDesc(isFinal, isAbstract)); 64 } 65 else if (!ScopeUtils.inEnumBlock(aAST)) { final ClassDesc desc = (ClassDesc) mClasses.peek(); 67 if ((modifiers != null) 68 && modifiers.branchContains(TokenTypes.LITERAL_PRIVATE)) 69 { 70 desc.reportPrivateCtor(); 71 } 72 else { 73 desc.reportNonPrivateCtor(); 74 } 75 } 76 } 77 78 79 public void leaveToken(DetailAST aAST) 80 { 81 if (aAST.getType() != TokenTypes.CLASS_DEF) { 82 return; 83 } 84 85 final ClassDesc desc = (ClassDesc) mClasses.pop(); 86 if (!desc.isDeclaredAsFinal() 87 && !desc.isDeclaredAsAbstract() 88 && desc.hasPrivateCtor() 89 && !desc.hasNonPrivateCtor()) 90 { 91 final String className = 92 aAST.findFirstToken(TokenTypes.IDENT).getText(); 93 log(aAST.getLineNo(), "final.class", className); 94 } 95 } 96 97 98 private static final class ClassDesc 99 { 100 101 private final boolean mDeclaredAsFinal; 102 103 104 private final boolean mDeclaredAsAbstract; 105 106 107 private boolean mHasNonPrivateCtor; 108 109 110 private boolean mHasPrivateCtor; 111 112 119 ClassDesc(boolean aDeclaredAsFinal, boolean aDeclaredAsAbstract) 120 { 121 mDeclaredAsFinal = aDeclaredAsFinal; 122 mDeclaredAsAbstract = aDeclaredAsAbstract; 123 } 124 125 126 void reportPrivateCtor() 127 { 128 mHasPrivateCtor = true; 129 } 130 131 132 void reportNonPrivateCtor() 133 { 134 mHasNonPrivateCtor = true; 135 } 136 137 141 boolean hasPrivateCtor() 142 { 143 return mHasPrivateCtor; 144 } 145 146 150 boolean hasNonPrivateCtor() 151 { 152 return mHasNonPrivateCtor; 153 } 154 155 159 boolean isDeclaredAsFinal() 160 { 161 return mDeclaredAsFinal; 162 } 163 164 168 boolean isDeclaredAsAbstract() 169 { 170 return mDeclaredAsAbstract; 171 } 172 173 177 public String toString() 178 { 179 return this.getClass().getName() 180 + "[" 181 + "final=" + mDeclaredAsFinal 182 + " abstract=" + mDeclaredAsAbstract 183 + " pctor=" + mHasPrivateCtor 184 + " ctor=" + mHasNonPrivateCtor 185 + "]"; 186 } 187 } 188 } 189 | Popular Tags |