private boolean isAdditive(Node n) { ASTAdditiveExpression add = n.getFirstDescendantOfType(ASTAdditiveExpression.class); // if the first descendant additive expression is deeper than 4 levels, // it belongs to a nested method call and not anymore to the append // argument. return add != null && add.getNthParent(4) == n; }
private int processAdditive(Node sn) { ASTAdditiveExpression additive = sn.getFirstDescendantOfType(ASTAdditiveExpression.class); if (additive == null) { return 0; } int anticipatedLength = 0; for (int ix = 0; ix < additive.jjtGetNumChildren(); ix++) { Node childNode = additive.jjtGetChild(ix); ASTLiteral literal = childNode.getFirstDescendantOfType(ASTLiteral.class); if (literal != null && literal.getImage() != null) { anticipatedLength += literal.getImage().length() - 2; } } return anticipatedLength; }
private String getExpressionVarName(Node e) { String assignedVar = getFirstNameImage(e); if (assignedVar == null) { ASTPrimarySuffix suffix = e.getFirstDescendantOfType(ASTPrimarySuffix.class); if (suffix != null) { assignedVar = suffix.getImage(); ASTPrimaryPrefix prefix = e.getFirstDescendantOfType(ASTPrimaryPrefix.class); if (prefix != null) { if (prefix.usesThisModifier()) { assignedVar = "this." + assignedVar; } else if (prefix.usesSuperModifier()) { assignedVar = "super." + assignedVar; } } } } return assignedVar; }
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)); } } } }
/** * Gets the image of the ASTName node found by * {@link Node#getFirstDescendantOfType(Class)} if it is the greatgrandchild * of the given node. * * E.g. * * <pre> * n = Expression || StatementExpression * PrimaryExpression * PrimaryPrefix * Name * </pre> * * @param n * the node to search * @return the image of the first ASTName or <code>null</code> */ protected String getFirstNameImage(Node n) { ASTName name = n.getFirstDescendantOfType(ASTName.class); if (name != null && name.getNthParent(3) == n) { return name.getImage(); } return null; }
/** * Determines the log level, that is used. It is either the called method name * itself or - in case java util logging is used, then it is the first argument of * the method call (if it exists). * * @param node the method call * @param methodCallName the called method name previously determined * @return the log level or <code>null</code> if it could not be determined */ private String getLogLevelName(Node node, String methodCallName) { if (!JAVA_UTIL_LOG_METHOD.equals(methodCallName) && !JAVA_UTIL_LOG_GUARD_METHOD.equals(methodCallName)) { return methodCallName; } String logLevel = null; ASTPrimarySuffix suffix = node.getFirstDescendantOfType(ASTPrimarySuffix.class); if (suffix != null) { ASTArgumentList argumentList = suffix.getFirstDescendantOfType(ASTArgumentList.class); if (argumentList != null && argumentList.jjtGetNumChildren() > 0) { // at least one argument - the log level. If the method call is "log", then a message might follow ASTName name = GuardLogStatementRule.<ASTName>getFirstChild(argumentList.jjtGetChild(0), ASTPrimaryExpression.class, ASTPrimaryPrefix.class, ASTName.class); String lastPart = getLastPartOfName(name); lastPart = lastPart.toLowerCase(Locale.ROOT); if (!lastPart.isEmpty()) { logLevel = lastPart; } } } return logLevel; }
private Entry<VariableNameDeclaration, List<NameOccurrence>> getIterableDeclOfIteratorLoop(VariableNameDeclaration indexDecl, Scope scope) { Node initializer = indexDecl.getNode().getFirstParentOfType(ASTVariableDeclarator.class) .getFirstChildOfType(ASTVariableInitializer.class); if (initializer == null) { return null; } ASTName nameNode = initializer.getFirstDescendantOfType(ASTName.class); if (nameNode == null) { // TODO : This can happen if we are calling a local / statically imported method that returns the iterable - currently unhandled return null; } String name = nameNode.getImage(); int dotIndex = name.indexOf('.'); if (dotIndex > 0) { name = name.substring(0, dotIndex); } return findDeclaration(name, scope); }
/** * Gets a list of NameDeclarations for all the fields that have type * ExpectedException and have a Rule annotation. * * @param classScope * The class scope to search for * @return See description */ private Map<String, List<NameOccurrence>> getRuleAnnotatedExpectedExceptions(Scope classScope) { Map<String, List<NameOccurrence>> result = new HashMap<>(); Map<NameDeclaration, List<NameOccurrence>> decls = classScope.getDeclarations(); for (Map.Entry<NameDeclaration, List<NameOccurrence>> entry : decls.entrySet()) { Node parent = entry.getKey().getNode().jjtGetParent().jjtGetParent().jjtGetParent(); if (parent.hasDescendantOfType(ASTMarkerAnnotation.class) && parent.getFirstChildOfType(ASTFieldDeclaration.class) != null) { String annot = parent.getFirstDescendantOfType(ASTMarkerAnnotation.class).jjtGetChild(0).getImage(); if (!"Rule".equals(annot) && !"org.junit.Rule".equals(annot)) { continue; } Node type = parent.getFirstDescendantOfType(ASTReferenceType.class); if (!"ExpectedException".equals(type.jjtGetChild(0).getImage())) { continue; } result.put(entry.getKey().getName(), entry.getValue()); } } return result; }
private Object process(Node node, Object data) { ASTClassOrInterfaceType cit = node.getFirstDescendantOfType(ASTClassOrInterfaceType.class); if (cit == null || !implClassNames.contains(cit.getImage())) { return data; } cit = cit.getFirstDescendantOfType(ASTClassOrInterfaceType.class); if (cit == null) { return data; } ASTVariableDeclaratorId decl = node.getFirstDescendantOfType(ASTVariableDeclaratorId.class); List<NameOccurrence> usages = decl.getUsages(); for (NameOccurrence no : usages) { ASTName name = (ASTName) no.getLocation(); Node n = name.jjtGetParent().jjtGetParent().jjtGetParent(); if (n instanceof ASTCastExpression) { addViolation(data, n); } } return null; } }
@Override public Object visit(ASTClassOrInterfaceBodyDeclaration node, Object data) { boolean inAnnotation = false; for (int i = 0; i < node.jjtGetNumChildren(); i++) { Node child = node.jjtGetChild(i); if (child instanceof ASTAnnotation) { ASTName annotationName = child.getFirstDescendantOfType(ASTName.class); if ("Test".equals(annotationName.getImage())) { inAnnotation = true; continue; } } if (child instanceof ASTMethodDeclaration) { boolean isJUnitMethod = isJUnitMethod((ASTMethodDeclaration) child, data); if (inAnnotation || isJUnitMethod) { List<Node> found = new ArrayList<>(); found.addAll((List<Node>) visit((ASTMethodDeclaration) child, data)); for (Node name : found) { addViolation(data, name); } } } inAnnotation = false; } return super.visit(node, data); }
private List<VariableAccess> markUsages(DataFlowNode inode) { // undefinitions was once a field... seems like it works fine as a local List<VariableAccess> undefinitions = new ArrayList<>(); Set<Map<NameDeclaration, List<NameOccurrence>>> variableDeclarations = collectDeclarations(inode); for (Map<NameDeclaration, List<NameOccurrence>> declarations : variableDeclarations) { for (Map.Entry<NameDeclaration, List<NameOccurrence>> entry : declarations.entrySet()) { NameDeclaration vnd = entry.getKey(); if (vnd.getNode().jjtGetParent() instanceof ASTFormalParameter) { // no definition/undefinition/references for parameters continue; } else if (vnd.getNode().jjtGetParent() .getFirstDescendantOfType(ASTVariableOrConstantInitializer.class) != null) { // add definition for initialized variables addVariableAccess(vnd.getNode(), new VariableAccess(VariableAccess.DEFINITION, vnd.getImage()), inode.getFlow()); } undefinitions.add(new VariableAccess(VariableAccess.UNDEFINITION, vnd.getImage())); for (NameOccurrence occurrence : entry.getValue()) { addAccess(occurrence, inode); } } } return undefinitions; }
private int getConstructorAppendsLength(final Node node) { final Node parent = node.getFirstParentOfType(ASTVariableDeclarator.class); int size = 0; if (parent != null) { final Node initializer = parent.getFirstChildOfType(ASTVariableInitializer.class); if (initializer != null) { final Node primExp = initializer.getFirstDescendantOfType(ASTPrimaryExpression.class); if (primExp != null) { for (int i = 0; i < primExp.jjtGetNumChildren(); i++) { final Node sn = primExp.jjtGetChild(i); if (!(sn instanceof ASTPrimarySuffix) || sn.getImage() != null) { continue; } size += processNode(sn); } } } } return size; }
private int processNode(Node sn) { int anticipatedLength = 0; if (sn != null) { ASTPrimaryPrefix xn = sn.getFirstDescendantOfType(ASTPrimaryPrefix.class); if (xn != null) { if (xn.jjtGetNumChildren() != 0 && xn.jjtGetChild(0) instanceof ASTLiteral) {
@Override public Object visit(ASTAllocationExpression node, Object data) { ASTClassOrInterfaceType declClassName = node.getFirstChildOfType(ASTClassOrInterfaceType.class); if (declClassName != null && TypeHelper.isA(declClassName, javax.crypto.spec.IvParameterSpec.class)) { Node firstArgument = null; ASTArguments arguments = node.getFirstChildOfType(ASTArguments.class); if (arguments.getArgumentCount() > 0) { firstArgument = arguments.getFirstChildOfType(ASTArgumentList.class).jjtGetChild(0); } if (firstArgument != null) { ASTPrimaryPrefix prefix = firstArgument.getFirstDescendantOfType(ASTPrimaryPrefix.class); validateProperIv(data, prefix); } } return data; }
@Override public Object visit(ASTAllocationExpression node, Object data) { ASTClassOrInterfaceType declClassName = node.getFirstChildOfType(ASTClassOrInterfaceType.class); if (declClassName != null && TypeHelper.isA(declClassName, SECRET_KEY_SPEC)) { Node firstArgument = null; ASTArguments arguments = node.getFirstChildOfType(ASTArguments.class); if (arguments.getArgumentCount() > 0) { firstArgument = arguments.getFirstChildOfType(ASTArgumentList.class).jjtGetChild(0); } if (firstArgument != null) { ASTPrimaryPrefix prefix = firstArgument.getFirstDescendantOfType(ASTPrimaryPrefix.class); validateProperKeyArgument(data, prefix); } } return data; }
/** * Determine if the constructor contains (or ends with) a String Literal * * @param node * @return 1 if the constructor contains string argument, else 0 */ private int checkConstructor(ASTVariableDeclaratorId node, Object data) { Node parent = node.jjtGetParent(); if (parent.jjtGetNumChildren() >= 2) { ASTAllocationExpression allocationExpression = parent.jjtGetChild(1) .getFirstDescendantOfType(ASTAllocationExpression.class); ASTArgumentList list = null; if (allocationExpression != null) { list = allocationExpression.getFirstDescendantOfType(ASTArgumentList.class); } if (list != null) { ASTLiteral literal = list.getFirstDescendantOfType(ASTLiteral.class); if (!isAdditive(list) && literal != null && literal.isStringLiteral()) { return 1; } return processAdditive(data, 0, list, node); } } return 0; }
/** * Gets the name of the variable returned. Some examples: <br> * for this.foo returns foo <br> * for foo returns foo <br> * for foo.bar returns foo.bar * * @param ret * a return statement to evaluate * @return the name of the variable associated or <code>null</code> if it * cannot be detected */ protected final String getReturnedVariableName(ASTReturnStatement ret) { if (hasTernaryCondition(ret) && hasTernaryNullCheck(ret)) { return ret.getFirstDescendantOfType(ASTConditionalExpression.class).jjtGetChild(0) .getFirstDescendantOfType(ASTName.class).getImage(); } final ASTName n = ret.getFirstDescendantOfType(ASTName.class); if (n != null) { return n.getImage(); } final ASTPrimarySuffix ps = ret.getFirstDescendantOfType(ASTPrimarySuffix.class); if (ps != null) { return ps.getImage(); } return null; }
for (int a = 0; a < argumentList.jjtGetNumChildren(); a++) { Node expression = argumentList.jjtGetChild(a); ASTPrimaryPrefix arg = expression.getFirstDescendantOfType(ASTPrimaryPrefix.class); String type = "<unknown>"; if (arg != null && arg.jjtGetNumChildren() > 0) {
private int processAdditive(Object data, int concurrentCount, Node sn, Node rootNode) { ASTAdditiveExpression additive = sn.getFirstDescendantOfType(ASTAdditiveExpression.class);
ASTArgumentList args = parent.getFirstDescendantOfType(ASTArgumentList.class); if (args != null) { ASTName arg = args.getFirstDescendantOfType(ASTName.class); if (declaration != null) { ASTType argType = declaration.getNode().jjtGetParent().jjtGetParent() .getFirstDescendantOfType(ASTType.class); if (argType != null && argType.jjtGetChild(0) instanceof ASTReferenceType && ((ASTReferenceType) argType.jjtGetChild(0)).isArray()) {