1 20 package com.puppycrawl.tools.checkstyle.checks.coding; 21 22 import java.util.LinkedList ; 23 24 import antlr.collections.AST; 25 26 import com.puppycrawl.tools.checkstyle.api.Check; 27 import com.puppycrawl.tools.checkstyle.api.DetailAST; 28 import com.puppycrawl.tools.checkstyle.api.ScopeUtils; 29 import com.puppycrawl.tools.checkstyle.api.TokenTypes; 30 31 38 public abstract class AbstractSuperCheck 39 extends Check 40 { 41 46 private class MethodNode 47 { 48 49 private DetailAST mMethod; 50 51 52 private boolean mCallsSuper; 53 54 58 public MethodNode(DetailAST aAST) 59 { 60 mMethod = aAST; 61 mCallsSuper = false; 62 } 63 64 67 public void setCallsSuper() 68 { 69 mCallsSuper = true; 70 } 71 72 78 public boolean getCallsSuper() 79 { 80 return mCallsSuper; 81 } 82 83 87 public DetailAST getMethod() 88 { 89 return mMethod; 90 } 91 } 92 93 94 private final LinkedList mMethodStack = new LinkedList (); 95 96 97 public int[] getDefaultTokens() 98 { 99 return new int[] { 100 TokenTypes.METHOD_DEF, 101 TokenTypes.LITERAL_SUPER, 102 }; 103 } 104 105 109 protected abstract String getMethodName(); 110 111 114 public void beginTree(DetailAST aRootAST) 115 { 116 mMethodStack.clear(); 117 } 118 119 123 public void visitToken(DetailAST aAST) 124 { 125 if (isOverridingMethod(aAST)) { 126 mMethodStack.add(new MethodNode(aAST)); 127 } 128 else if (isSuperCall(aAST)) { 129 final MethodNode methodNode = (MethodNode) mMethodStack.getLast(); 130 methodNode.setCallsSuper(); 131 } 132 } 133 134 141 private boolean isSuperCall(DetailAST aAST) 142 { 143 if (aAST.getType() != TokenTypes.LITERAL_SUPER) { 144 return false; 145 } 146 DetailAST parent = aAST.getParent(); 148 if ((parent == null) || (parent.getType() != TokenTypes.DOT)) { 149 return false; 150 } 151 152 AST sibling = aAST.getNextSibling(); 154 if ((sibling != null) 156 && (sibling.getType() == TokenTypes.TYPE_ARGUMENTS)) 157 { 158 sibling = sibling.getNextSibling(); 159 } 160 if ((sibling == null) || (sibling.getType() != TokenTypes.IDENT)) { 161 return false; 162 } 163 final String name = sibling.getText(); 164 if (!getMethodName().equals(name)) { 165 return false; 166 } 167 168 final DetailAST args = (DetailAST) parent.getNextSibling(); 170 if ((args == null) || (args.getType() != TokenTypes.ELIST)) { 171 return false; 172 } 173 if (args.getChildCount() != 0) { 174 return false; 175 } 176 177 while (parent != null) { 179 if (parent.getType() == TokenTypes.METHOD_DEF) { 180 return isOverridingMethod(parent); 181 } 182 else if ((parent.getType() == TokenTypes.CTOR_DEF) 183 || (parent.getType() == TokenTypes.INSTANCE_INIT)) 184 { 185 return false; 186 } 187 parent = parent.getParent(); 188 } 189 return false; 190 } 191 192 195 public void leaveToken(DetailAST aAST) 196 { 197 if (isOverridingMethod(aAST)) { 198 final MethodNode methodNode = 199 (MethodNode) mMethodStack.removeLast(); 200 if (!methodNode.getCallsSuper()) { 201 final DetailAST methodAST = methodNode.getMethod(); 202 final DetailAST nameAST = 203 methodAST.findFirstToken(TokenTypes.IDENT); 204 log(nameAST.getLineNo(), nameAST.getColumnNo(), 205 "missing.super.call", 206 new Object [] {nameAST.getText()}); 207 } 208 } 209 } 210 211 217 private boolean isOverridingMethod(DetailAST aAST) 218 { 219 if ((aAST.getType() != TokenTypes.METHOD_DEF) 220 || ScopeUtils.inInterfaceOrAnnotationBlock(aAST)) 221 { 222 return false; 223 } 224 final DetailAST nameAST = aAST.findFirstToken(TokenTypes.IDENT); 225 final String name = nameAST.getText(); 226 if (!getMethodName().equals(name)) { 227 return false; 228 } 229 final DetailAST params = aAST.findFirstToken(TokenTypes.PARAMETERS); 230 return (params.getChildCount() == 0); 231 } 232 } 233 | Popular Tags |