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.Scope; 24 import com.puppycrawl.tools.checkstyle.api.ScopeUtils; 25 import com.puppycrawl.tools.checkstyle.api.TokenTypes; 26 27 59 public class DesignForExtensionCheck extends Check 60 { 61 62 public int[] getDefaultTokens() 63 { 64 return new int[] {TokenTypes.METHOD_DEF}; 65 } 66 67 68 public void visitToken(DetailAST aAST) 69 { 70 if (ScopeUtils.inInterfaceOrAnnotationBlock(aAST)) { 72 return; 73 } 74 75 final DetailAST modifiers = aAST.findFirstToken(TokenTypes.MODIFIERS); 77 if (modifiers.branchContains(TokenTypes.LITERAL_PRIVATE) 78 || modifiers.branchContains(TokenTypes.ABSTRACT) 79 || modifiers.branchContains(TokenTypes.FINAL) 80 || modifiers.branchContains(TokenTypes.LITERAL_STATIC)) 81 { 82 return; 83 } 84 85 if (!ScopeUtils.getSurroundingScope(aAST).isIn(Scope.PROTECTED)) { 88 return; 89 } 90 91 final DetailAST implementation = aAST.findFirstToken(TokenTypes.SLIST); 95 if ((implementation != null) 96 && (implementation.getFirstChild().getType() == TokenTypes.RCURLY)) 97 { 98 return; 99 } 100 101 final DetailAST classDef = findContainingClass(aAST); 103 final DetailAST classMods = 104 classDef.findFirstToken(TokenTypes.MODIFIERS); 105 if ((classDef.getType() == TokenTypes.ENUM_DEF) 106 || classMods.branchContains(TokenTypes.FINAL)) 107 { 108 return; 109 } 110 111 final DetailAST objBlock = classDef.findFirstToken(TokenTypes.OBJBLOCK); 113 114 boolean hasDefaultConstructor = true; 115 boolean hasExplNonPrivateCtor = false; 116 117 DetailAST candidate = (DetailAST) objBlock.getFirstChild(); 118 119 while (candidate != null) { 120 if (candidate.getType() == TokenTypes.CTOR_DEF) { 121 hasDefaultConstructor = false; 122 123 final DetailAST ctorMods = 124 candidate.findFirstToken(TokenTypes.MODIFIERS); 125 if (!ctorMods.branchContains(TokenTypes.LITERAL_PRIVATE)) { 126 hasExplNonPrivateCtor = true; 127 break; 128 } 129 } 130 candidate = (DetailAST) candidate.getNextSibling(); 131 } 132 133 if (hasDefaultConstructor || hasExplNonPrivateCtor) { 134 final String name = aAST.findFirstToken(TokenTypes.IDENT).getText(); 135 log(aAST.getLineNo(), aAST.getColumnNo(), 136 "design.forExtension", name); 137 } 138 139 140 141 } 142 143 148 private DetailAST findContainingClass(DetailAST aAST) 149 { 150 DetailAST searchAST = aAST; 151 while ((searchAST.getType() != TokenTypes.CLASS_DEF) 152 && (searchAST.getType() != TokenTypes.ENUM_DEF)) 153 { 154 searchAST = searchAST.getParent(); 155 } 156 return searchAST; 157 } 158 } 159 | Popular Tags |