/** * Adds all methods called on this instance from within this Node. */ private static void addCalledMethodsOfNode(Node node, List<MethodInvocation> calledMethods, String className) { List<ASTPrimaryExpression> expressions = new ArrayList<>(); node.findDescendantsOfType(ASTPrimaryExpression.class, expressions, !(node instanceof AccessNode)); addCalledMethodsOfNodeImpl(expressions, calledMethods, className); }
/** * Evaluates the number of paths through a boolean expression. This is the total number of {@code &&} and {@code ||} * operators appearing in the expression. This is used in the calculation of cyclomatic and n-path complexity. * * @param expr Expression to analyse * * @return The number of paths through the expression */ public static int booleanExpressionComplexity(Node expr) { if (expr == null) { return 0; } List<ASTConditionalAndExpression> andNodes = expr.findDescendantsOfType(ASTConditionalAndExpression.class); List<ASTConditionalOrExpression> orNodes = expr.findDescendantsOfType(ASTConditionalOrExpression.class); int complexity = 0; if (expr instanceof ASTConditionalOrExpression || expr instanceof ASTConditionalAndExpression) { complexity++; } for (ASTConditionalOrExpression element : orNodes) { complexity += element.jjtGetNumChildren() - 1; } for (ASTConditionalAndExpression element : andNodes) { complexity += element.jjtGetNumChildren() - 1; } return complexity; }
/** * Checks to see if there is string concatenation in the node. * * This method checks if it's additive with respect to the append method * only. * * @param n * Node to check * @return true if the node has an additive expression (i.e. "Hello " + * Const.WORLD) */ private boolean isAdditive(Node n) { List<ASTAdditiveExpression> lstAdditive = n.findDescendantsOfType(ASTAdditiveExpression.class); if (lstAdditive.isEmpty()) { return false; } // if there are more than 1 set of arguments above us we're not in the // append // but a sub-method call for (int ix = 0; ix < lstAdditive.size(); ix++) { ASTAdditiveExpression expr = lstAdditive.get(ix); if (expr.getParentsOfType(ASTArgumentList.class).size() != 1) { return false; } } return true; }
/** * Checks whether the given target is in the argument list. If this is the * case, then the target (root exception) is used as the cause. * * @param target * @param baseNode */ private boolean checkForTargetUsage(String target, Node baseNode) { boolean match = false; if (target != null && baseNode != null) { // TODO : use Node.findDescendantsOfType(ASTName.class, true) on 7.0.0 List<ASTName> nameNodes = new ArrayList<>(); baseNode.findDescendantsOfType(ASTName.class, nameNodes, true); for (ASTName nameNode : nameNodes) { if (target.equals(nameNode.getImage())) { boolean isPartOfStringConcatenation = isStringConcat(nameNode, baseNode); if (!isPartOfStringConcatenation) { match = true; break; } } } } return match; }
private boolean isAnnotatedOverride(ASTMethodDeclaration decl) { List<ASTMarkerAnnotation> annotations = decl.jjtGetParent().findDescendantsOfType(ASTMarkerAnnotation.class); for (ASTMarkerAnnotation ann : annotations) { // TODO consider making a method to get the annotations of a method if (ann.getFirstChildOfType(ASTName.class).getImage().equals("Override")) { return true; } } return false; }
/** * Adds a VariableAccess to a dataflow node. * * @param node * location of the access of a variable * @param va * variable access to add * @param flow * dataflownodes that can contain the node. */ private void addVariableAccess(Node node, VariableAccess va, List<DataFlowNode> flow) { // backwards to find the right inode (not a method declaration) for (int i = flow.size() - 1; i > 0; i--) { DataFlowNode inode = flow.get(i); if (inode.getNode() == null) { continue; } List<? extends Node> children = inode.getNode().findDescendantsOfType(node.getClass()); for (Node n : children) { if (node.equals(n)) { List<VariableAccess> v = new ArrayList<>(); v.add(va); inode.setVariableAccess(v); return; } } } }
/** * Adds a VariableAccess to a dataflow node. * * @param node * location of the access of a variable * @param va * variable access to add * @param flow * dataflownodes that can contain the node. */ private void addVariableAccess(Node node, VariableAccess va, List<DataFlowNode> flow) { // backwards to find the right inode (not a method declaration) for (int i = flow.size() - 1; i > 0; i--) { DataFlowNode inode = flow.get(i); if (inode.getNode() == null) { continue; } List<? extends Node> children = inode.getNode().findDescendantsOfType(node.getClass()); for (Node n : children) { if (node.equals(n)) { List<VariableAccess> v = new ArrayList<>(); v.add(va); inode.setVariableAccess(v); return; } } } }
private boolean isEqualsViolation(Node parent) { // 3. child: equals if (parent.jjtGetChild(2).hasImageEqualTo("equals")) { // 4. child: the arguments of equals, there must be exactly one and // it must be "" List<ASTArgumentList> argList = parent.jjtGetChild(3).findDescendantsOfType(ASTArgumentList.class); if (argList.size() == 1) { List<ASTLiteral> literals = argList.get(0).findDescendantsOfType(ASTLiteral.class); return literals.size() == 1 && literals.get(0).hasImageEqualTo("\"\""); } } return false; }
/** * TODO modify usages to use symbol table Tells if the variable name is a * local variable declared in the method. * * @param vn * the variable name * @param node * the ASTMethodDeclaration where the local variable name will be * searched * @return <code>true</code> if the method declaration contains any local * variable named vn and <code>false</code> in other case */ protected boolean isLocalVariable(String vn, Node node) { final List<ASTLocalVariableDeclaration> lvars = node.findDescendantsOfType(ASTLocalVariableDeclaration.class); if (lvars != null) { for (ASTLocalVariableDeclaration lvd : lvars) { final ASTVariableDeclaratorId vid = lvd.getFirstDescendantOfType(ASTVariableDeclaratorId.class); if (vid != null && vid.hasImageEqualTo(vn)) { return true; } } } return false; }
private static List<String> getMethodDeclaratorParameterTypes(Node methodOrConstructorDeclarator) { List<ASTFormalParameter> parameters = methodOrConstructorDeclarator .findDescendantsOfType(ASTFormalParameter.class); List<String> parameterTypes = new ArrayList<>(); if (parameters != null) { for (ASTFormalParameter p : parameters) { ASTType type = p.getFirstChildOfType(ASTType.class); if (type.jjtGetChild(0) instanceof ASTPrimitiveType) { parameterTypes.add(type.jjtGetChild(0).getImage()); } else if (type.jjtGetChild(0) instanceof ASTReferenceType) { parameterTypes.add("ref"); } else { parameterTypes.add("<unkown>"); } } } return parameterTypes; }
private int getInitialLength(Node node) { Node block = node.getFirstParentOfType(ASTBlockStatement.class); if (block == null) { block = node.getFirstParentOfType(ASTFieldDeclaration.class); if (block == null) { block = node.getFirstParentOfType(ASTFormalParameter.class); } } List<ASTLiteral> literals = block.findDescendantsOfType(ASTLiteral.class); if (literals.size() == 1) { ASTLiteral literal = literals.get(0); String str = literal.getImage(); if (str != null && isStringOrCharLiteral(literal)) { return str.length() - 2; // take off the quotes } } return 0; }
/** * Tells if the node contains a Test annotation with an expected exception. */ private boolean isExpectAnnotated(Node methodParent) { List<ASTNormalAnnotation> annotations = methodParent.findDescendantsOfType(ASTNormalAnnotation.class); for (ASTNormalAnnotation annotation : annotations) { ASTName name = annotation.getFirstChildOfType(ASTName.class); if (name != null && TypeHelper.isA(name, JUNIT4_CLASS_NAME)) { List<ASTMemberValuePair> memberValues = annotation.findDescendantsOfType(ASTMemberValuePair.class); for (ASTMemberValuePair pair : memberValues) { if ("expected".equals(pair.getImage())) { return true; } } } } return false; }
/** * Returns {@code true} if the node has only one {@link ASTConstructorDeclaration} * child node and the constructor has empty body or simply invokes the superclass * constructor with no arguments. * * @param node the node to check */ private boolean isExplicitDefaultConstructor(Node node) { List<ASTConstructorDeclaration> nodes = node.findDescendantsOfType(ASTConstructorDeclaration.class); if (nodes.size() != 1) { return false; } ASTConstructorDeclaration cdnode = nodes.get(0); return cdnode.getParameterCount() == 0 && !hasIgnoredAnnotation(cdnode) && !cdnode.hasDescendantOfType(ASTBlockStatement.class) && !cdnode.hasDescendantOfType(ASTNameList.class) && hasDefaultConstructorInvocation(cdnode); }
continue; List<ASTBlockStatement> blocks = trySt.jjtGetChild(0).findDescendantsOfType(ASTBlockStatement.class); if (blocks.isEmpty()) { continue;
private void recursivelyEvaluateCRUDMethodCalls(final AbstractApexNode<?> self, final Set<ASTMethodCallExpression> innerMethodCalls, final ASTBlockStatement blockStatement) { if (blockStatement != null) { int numberOfStatements = blockStatement.jjtGetNumChildren(); for (int i = 0; i < numberOfStatements; i++) { Node n = blockStatement.jjtGetChild(i); if (n instanceof ASTIfElseBlockStatement) { List<ASTBlockStatement> innerBlocks = n.findDescendantsOfType(ASTBlockStatement.class); for (ASTBlockStatement innerBlock : innerBlocks) { recursivelyEvaluateCRUDMethodCalls(self, innerMethodCalls, innerBlock); } } AbstractApexNode<?> match = n.getFirstDescendantOfType(self.getClass()); if (Objects.equal(match, self)) { break; } ASTMethodCallExpression methodCall = n.getFirstDescendantOfType(ASTMethodCallExpression.class); if (methodCall != null) { mapCallToMethodDecl(self, innerMethodCalls, Arrays.asList(methodCall)); } } } }
private boolean hasOverrideAnnotation(ASTMethodDeclaration node) { int childIndex = node.jjtGetChildIndex(); for (int i = 0; i < childIndex; i++) { Node previousSibling = node.jjtGetParent().jjtGetChild(i); List<ASTMarkerAnnotation> annotations = previousSibling.findDescendantsOfType(ASTMarkerAnnotation.class); for (ASTMarkerAnnotation annotation : annotations) { ASTName name = annotation.getFirstChildOfType(ASTName.class); if (name != null && (name.hasImageEqualTo("Override") || name.hasImageEqualTo("java.lang.Override"))) { return true; } } } return false; } }
private void checkForResources(Node node, Object data) { List<ASTLocalVariableDeclaration> vars = node.findDescendantsOfType(ASTLocalVariableDeclaration.class); List<ASTVariableDeclaratorId> ids = new ArrayList<>(); // find all variable references to Connection objects for (ASTLocalVariableDeclaration var : vars) { ASTType type = var.getTypeNode(); if (type != null && type.jjtGetChild(0) instanceof ASTReferenceType) { ASTReferenceType ref = (ASTReferenceType) type.jjtGetChild(0); if (ref.jjtGetChild(0) instanceof ASTClassOrInterfaceType) { ASTClassOrInterfaceType clazz = (ASTClassOrInterfaceType) ref.jjtGetChild(0); if (clazz.getType() != null && types.contains(clazz.getType().getName()) || clazz.getType() == null && simpleTypes.contains(toSimpleType(clazz.getImage())) && !clazz.isReferenceToClassSameCompilationUnit() || types.contains(clazz.getImage()) && !clazz.isReferenceToClassSameCompilationUnit()) { ASTVariableDeclaratorId id = var.getFirstDescendantOfType(ASTVariableDeclaratorId.class); ids.add(id); } } } } // if there are connections, ensure each is closed. for (ASTVariableDeclaratorId x : ids) { ensureClosed((ASTLocalVariableDeclaration) x.jjtGetParent().jjtGetParent(), x, data); } }
private boolean doesNodeContainJUnitAnnotation(Node node, String annotationTypeClassName) { List<ASTAnnotation> annotations = node.findDescendantsOfType(ASTAnnotation.class); for (ASTAnnotation annotation : annotations) { Node annotationTypeNode = annotation.jjtGetChild(0); TypeNode annotationType = (TypeNode) annotationTypeNode; if (annotationType.getType() == null) { ASTName name = annotationTypeNode.getFirstChildOfType(ASTName.class); if (name != null && (name.hasImageEqualTo("Test") || name.hasImageEqualTo(annotationTypeClassName))) { return true; } } else if (TypeHelper.isA(annotationType, annotationTypeClassName)) { return true; } } return false; }
return data; List<ASTLiteral> literals = parent.findDescendantsOfType(ASTLiteral.class); for (int l = 0; l < literals.size(); l++) { ASTLiteral literal = literals.get(l);
addViolationWithMessage(data, child, child.getXPathNodeName() + " should be on line " + lineNumber); List<ASTEqualityExpression> conditions = child.findDescendantsOfType(ASTEqualityExpression.class);