/** * Determines whether or not the given AST is in a valid hash code method. A valid hash code * method is considered to be a method of the signature {@code public int hashCode()}. * * @param ast the AST from which to search for an enclosing hash code method definition * @return {@code true} if {@code ast} is in the scope of a valid hash code method */ private boolean isInHashCodeMethod(DetailAST ast) { // if not in a code block, can't be in hashCode() if (!ScopeUtils.inCodeBlock(ast)) { return false; } // find the method definition AST DetailAST methodDefAST = ast.getParent(); while (null != methodDefAST && TokenTypes.METHOD_DEF != methodDefAST.getType()) { methodDefAST = methodDefAST.getParent(); } if (null == methodDefAST) { return false; } // Check for 'hashCode' name. final DetailAST identAST = methodDefAST.findFirstToken(TokenTypes.IDENT); if (!"hashCode".equals(identAST.getText())) { return false; } // Check for no arguments. final DetailAST paramAST = methodDefAST.findFirstToken(TokenTypes.PARAMETERS); // we are in a 'public int hashCode()' method! The compiler will ensure // the method returns an 'int' and is public. return 0 == paramAST.getChildCount(); }
/** * process modifiers * * @param ast ast of Modifiers */ private void processModifiers(DetailAST ast) { final ScopeState state = scopeStates.peek(); if (ast.findFirstToken(TokenTypes.LITERAL_STATIC) != null) { if (state.currentScopeState > STATE_STATIC_VARIABLE_DEF) { if (!ignoreModifiers || state.currentScopeState > STATE_INSTANCE_VARIABLE_DEF) { log(ast, MSG_STATIC); } } else { state.currentScopeState = STATE_STATIC_VARIABLE_DEF; } } else { if (state.currentScopeState > STATE_INSTANCE_VARIABLE_DEF) { log(ast, MSG_INSTANCE); } else if (state.currentScopeState == STATE_STATIC_VARIABLE_DEF) { state.declarationAccess = Scope.PUBLIC; state.currentScopeState = STATE_INSTANCE_VARIABLE_DEF; } } final Scope access = ScopeUtils.getScopeFromMods(ast); if (state.declarationAccess.compareTo(access) > 0) { if (!ignoreModifiers) { log(ast, MSG_ACCESS); } } else { state.declarationAccess = access; } }
/** * Finds the constant definition that contains aAST. * * @param ast the AST * @return the constant def or null if ast is not contained in a constant definition */ private DetailAST findContainingConstantDef(DetailAST ast) { DetailAST varDefAST = ast; while (varDefAST != null && varDefAST.getType() != TokenTypes.VARIABLE_DEF && varDefAST.getType() != TokenTypes.ENUM_CONSTANT_DEF) { varDefAST = varDefAST.getParent(); } // no containing variable definition? if (varDefAST == null) { return null; } // implicit constant? if (ScopeUtils.inInterfaceOrAnnotationBlock(varDefAST) || varDefAST.getType() == TokenTypes.ENUM_CONSTANT_DEF) { return varDefAST; } // explicit constant final DetailAST modifiersAST = varDefAST.findFirstToken(TokenTypes.MODIFIERS); if (modifiersAST.branchContains(TokenTypes.FINAL)) { return varDefAST; } return null; }
/** {@inheritDoc} */ @Override public boolean isValidOn(final DetailAST ast) { final int type = ast.getType(); return type == TokenTypes.METHOD_DEF && !ast.branchContains(TokenTypes.LITERAL_STATIC) && ScopeUtils.getScopeFromMods(ast.findFirstToken(TokenTypes.MODIFIERS)) != Scope.PRIVATE; }
@Override public void visitToken(DetailAST ast) { // do not check local variables and // fields declared in interface/annotations if (ScopeUtils.isLocalVariableDef(ast) || ScopeUtils.inInterfaceOrAnnotationBlock(ast)) { return; } final DetailAST assign = ast.findFirstToken(TokenTypes.ASSIGN); if (assign == null) { // no assign - no check return; } final DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS); if (modifiers != null && modifiers.branchContains(TokenTypes.FINAL)) { // do not check final variables return; } final DetailAST type = ast.findFirstToken(TokenTypes.TYPE); final DetailAST ident = ast.findFirstToken(TokenTypes.IDENT); final DetailAST exprStart = assign.getFirstChild().getFirstChild(); if (isObjectType(type) && exprStart.getType() == TokenTypes.LITERAL_NULL) { log(ident, MSG_KEY, ident.getText(), "null"); } final int primitiveType = type.getFirstChild().getType(); if (primitiveType == TokenTypes.LITERAL_BOOLEAN && exprStart.getType() == TokenTypes.LITERAL_FALSE) { log(ident, MSG_KEY, ident.getText(), "false"); } if (isNumericType(primitiveType) && isZero(exprStart)) { log(ident, MSG_KEY, ident.getText(), "0"); } if (primitiveType == TokenTypes.LITERAL_CHAR && (isZero(exprStart) || exprStart.getType() == TokenTypes.CHAR_LITERAL && "'\\0'".equals(exprStart.getText()))) { log(ident, MSG_KEY, ident.getText(), "\\0"); } }
/** {@inheritDoc} */ @Override public boolean isValidOn(final DetailAST ast) { final int type = ast.getType(); return type == TokenTypes.PACKAGE_DEF || type == TokenTypes.CLASS_DEF || type == TokenTypes.INTERFACE_DEF || type == TokenTypes.ENUM_DEF || type == TokenTypes.ANNOTATION_DEF || type == TokenTypes.METHOD_DEF || type == TokenTypes.CTOR_DEF || type == TokenTypes.VARIABLE_DEF && !ScopeUtils.isLocalVariableDef(ast); }
@Override public void visitToken(DetailAST ast) { switch (ast.getType()) { case TokenTypes.OBJBLOCK: case TokenTypes.SLIST: case TokenTypes.LITERAL_FOR: case TokenTypes.METHOD_DEF: case TokenTypes.CTOR_DEF: case TokenTypes.STATIC_INIT: case TokenTypes.INSTANCE_INIT: scopeStack.push(new HashMap<String, DetailAST>()); break; case TokenTypes.PARAMETER_DEF: if (!inLambda(ast) && !ast.branchContains(TokenTypes.FINAL) && !inAbstractOrNativeMethod(ast) && !ScopeUtils.inInterfaceBlock(ast)) { insertVariable(ast); } break; case TokenTypes.VARIABLE_DEF: if (ast.getParent().getType() != TokenTypes.OBJBLOCK && isVariableInForInit(ast) && shouldCheckEnhancedForLoopVariable(ast) && !ast.branchContains(TokenTypes.FINAL)) { insertVariable(ast); } break; case TokenTypes.IDENT: final int parentType = ast.getParent().getType(); if (isAssignOperator(parentType) && ast.getParent().getFirstChild() == ast) { removeVariable(ast); } break; default: } }
/** {@inheritDoc} */ @Override public boolean isValidOn(final DetailAST ast) { final int type = ast.getType(); return type == TokenTypes.VARIABLE_DEF && !ScopeUtils.isLocalVariableDef(ast); }