@Override public boolean visitMethodDeclaration(MethodDeclaration node) { ResolvedNode resolved = context.resolve(node); if (resolved instanceof ResolvedMethod) { ResolvedMethod method = (ResolvedMethod) resolved; checkCallSuper(context, node, method); } return false; } };
@Override public void afterVisitVariableReference(VariableReference node) { if (mTypes.get(node) == null) { ResolvedNode resolved = mContext.resolve(node); if (resolved instanceof ResolvedVariable) { ResolvedClass resolvedClass = mVariableTypes.get(resolved); if (resolvedClass != null) { mTypes.put(node, resolvedClass); } } } }
@Override public boolean visitMethodInvocation(@NonNull MethodInvocation call) { JavaParser.ResolvedNode resolved = mContext.resolve(call); if (resolved instanceof JavaParser.ResolvedMethod) { if (!checkTransactionHasACommit(mContext, call)) { showCommitMessage(mContext, call); } } return false; }
@Override public void afterVisitVariableDefinitionEntry(VariableDefinitionEntry node) { Expression initializer = node.astInitializer(); if (initializer != null) { ResolvedClass resolvedClass = mTypes.get(initializer); if (resolvedClass != null) { mTypes.put(node, resolvedClass); ResolvedNode variable = mContext.resolve(node); if (variable instanceof ResolvedVariable) { mVariableTypes.put((ResolvedVariable) variable, resolvedClass); } } } }
@Override public boolean visitSuper(Super node) { ResolvedNode resolved = null; if (node.getParent() instanceof MethodInvocation) { resolved = mContext.resolve(node.getParent()); } if (resolved == null) { resolved = mContext.resolve(node); } if (mMethod.equals(resolved)) { mCallsSuper = true; return true; } return false; }
@Override public boolean visitVariableDefinitionEntry(VariableDefinitionEntry node) { Expression initializer = node.astInitializer(); if (initializer instanceof VariableReference) { JavaParser.ResolvedNode resolved = mContext.resolve(initializer); //noinspection SuspiciousMethodCalls if (resolved != null && mVariables.contains(resolved)) { JavaParser.ResolvedNode resolvedVariable = mContext.resolve(node); if (resolvedVariable instanceof JavaParser.ResolvedVariable) { JavaParser.ResolvedVariable variable = (JavaParser.ResolvedVariable) resolvedVariable; mVariables.add(variable); } } } return super.visitVariableDefinitionEntry(node); }
@Override public boolean visitVariableDefinitionEntry(VariableDefinitionEntry node) { Expression initializer = node.astInitializer(); if (initializer instanceof VariableReference) { ResolvedNode resolved = mContext.resolve(initializer); //noinspection SuspiciousMethodCalls if (resolved != null && mVariables.contains(resolved)) { ResolvedNode resolvedVariable = mContext.resolve(node); if (resolvedVariable instanceof ResolvedVariable) { ResolvedVariable variable = (ResolvedVariable) resolvedVariable; mVariables.add(variable); } else if (resolvedVariable instanceof ResolvedField) { mEscapes = true; } } } return super.visitVariableDefinitionEntry(node); }
@Override public boolean visitReturn(Return node) { Expression value = node.astValue(); if (value instanceof VariableReference) { ResolvedNode resolved = mContext.resolve(value); //noinspection SuspiciousMethodCalls if (resolved != null && mVariables.contains(resolved)) { mEscapes = true; } } return super.visitReturn(node); } }
private static boolean isCallOnWebView(JavaContext context, MethodInvocation call) { ResolvedNode resolved = context.resolve(call); if (!(resolved instanceof ResolvedMethod)) { return false; } ResolvedMethod method = (ResolvedMethod) resolved; return method.getContainingClass().matches(WEB_VIEW_CLS); }
@Override public void afterVisitBinaryExpression(BinaryExpression node) { if (node.astOperator() == BinaryOperator.ASSIGN) { Expression rhs = node.astRight(); ResolvedClass resolvedClass = mTypes.get(rhs); if (resolvedClass != null) { Expression lhs = node.astLeft(); mTypes.put(lhs, resolvedClass); ResolvedNode variable = mContext.resolve(lhs); if (variable instanceof ResolvedVariable) { mVariableTypes.put((ResolvedVariable) variable, resolvedClass); } } } }
public ResolvedClass getType() { Expression first = mTargetCall.astArguments().first(); ResolvedClass resolvedClass = mTypes.get(first); if (resolvedClass == null) { ResolvedNode resolved = mContext.resolve(first); if (resolved instanceof ResolvedVariable) { resolvedClass = mVariableTypes.get(resolved); if (resolvedClass == null) { return ((ResolvedVariable)resolved).getType().getTypeClass(); } } } return resolvedClass; }
@Override public void afterVisitConstructorInvocation(@NonNull ConstructorInvocation node) { ResolvedNode resolved = mContext.resolve(node); if (resolved instanceof ResolvedMethod) { ResolvedMethod method = (ResolvedMethod) resolved; mTypes.put(node, method.getContainingClass()); } else { // Implicit constructor? TypeDescriptor type = mContext.getType(node); if (type != null) { ResolvedClass typeClass = type.getTypeClass(); if (typeClass != null) { mTypes.put(node, typeClass); } } } }
private static boolean isAddReplaceOpen(@NonNull JavaContext context, @NonNull MethodInvocation node) { String methodName = node.astName().astValue(); if (ADD_TRANSACTION.equals(methodName) || OPEN_TRANSACTION.equals(methodName) || REPLACE_TRANSACTION.equals(methodName)) { JavaParser.ResolvedNode resolved = context.resolve(node); if (resolved instanceof JavaParser.ResolvedMethod) { JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) resolved; JavaParser.ResolvedClass containingClass = method.getContainingClass(); if (containingClass.isSubclassOf(ACTIVITY_MANAGER, false)) { return true; } } } return false; }
private static boolean isStringParameter( @NonNull Expression expression, @NonNull JavaContext context) { if (expression instanceof StringLiteral) { return true; } else { ResolvedNode resolvedNode = context.resolve(expression); if (resolvedNode instanceof ResolvedField) { if (((ResolvedField) resolvedNode).getValue() instanceof String) { return true; } } } return false; } }
private static void report(JavaContext context, MethodInvocation node) { // Make sure the call is on a view JavaParser.ResolvedNode resolved = context.resolve(node); if (resolved instanceof JavaParser.ResolvedMethod) { JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) resolved; JavaParser.ResolvedClass containingClass = method.getContainingClass(); if (!containingClass.isSubclassOf(CLASS_VIEW, false)) { return; } } String name = node.astName().astValue(); String suggestion = Character.toLowerCase(name.charAt(2)) + name.substring(3); String message = String.format( // Keep in sync with {@link #getOldValue} and {@link #getNewValue} below! "Suspicious method call; should probably call \"`%1$s`\" rather than \"`%2$s`\"", suggestion, name); context.report(ISSUE, node, context.getLocation(node.astName()), message); }
private static boolean isSharedPreferenceGetString(@NonNull JavaContext context, @NonNull MethodInvocation call) { if (!GET_STRING_METHOD.equals(call.astName().astValue())) { return false; } JavaParser.ResolvedNode resolved = context.resolve(call); if (resolved instanceof JavaParser.ResolvedMethod) { JavaParser.ResolvedMethod resolvedMethod = (JavaParser.ResolvedMethod) resolved; JavaParser.ResolvedClass containingClass = resolvedMethod.getContainingClass(); return containingClass.isSubclassOf(ANDROID_CONTENT_SHARED_PREFERENCES, false); } return false; // not certain }
private static boolean isBeginTransaction(@NonNull JavaContext context, @NonNull MethodInvocation node) { String methodName = node.astName().astValue(); assert methodName.equals(BEGIN_TRANSACTION) : methodName; if (BEGIN_TRANSACTION.equals(methodName)) { ResolvedNode resolved = context.resolve(node); if (resolved instanceof ResolvedMethod) { ResolvedMethod method = (ResolvedMethod) resolved; ResolvedClass containingClass = method.getContainingClass(); if (containingClass.isSubclassOf(FRAGMENT_MANAGER_CLS, false) || containingClass.isSubclassOf(FRAGMENT_MANAGER_V4_CLS, false)) { return true; } } } return false; }
private static boolean isMethodOnFragmentClass( @NonNull JavaContext context, @NonNull MethodInvocation call, @NonNull String fragmentClass, @NonNull String v4FragmentClass) { ResolvedNode resolved = context.resolve(call); if (resolved instanceof ResolvedMethod) { ResolvedClass containingClass = ((ResolvedMethod) resolved).getContainingClass(); return containingClass.isSubclassOf(fragmentClass, false) || containingClass.isSubclassOf(v4FragmentClass, false); } return false; }
@Override public void visitMethod(@NonNull JavaContext context, @Nullable AstVisitor visitor, @NonNull MethodInvocation node) { ResolvedNode resolved = context.resolve(node); if (resolved instanceof ResolvedMethod) { ResolvedMethod method = (ResolvedMethod) resolved; if (method.getContainingClass().matches("android.app.AlarmManager") && method.getArgumentCount() == 4) { ensureAtLeast(context, node, 1, 5000L); ensureAtLeast(context, node, 2, 60000L); } } }
@Override public void visitMethod(@NonNull JavaContext context, @Nullable AstVisitor visitor, @NonNull MethodInvocation node) { ResolvedNode resolved = context.resolve(node); if (!(resolved instanceof ResolvedMethod) || !((ResolvedMethod) resolved).getContainingClass() .isSubclassOf(PACKAGE_MANAGER_CLASS, false)) { return; } StrictListAccessor<Expression, MethodInvocation> argumentList = node.astArguments(); // Ignore if the method doesn't fit our description. if (argumentList != null && argumentList.size() == 2) { TypeDescriptor firstParameterType = context.getType(argumentList.first()); if (firstParameterType != null && firstParameterType.matchesSignature(JavaParser.TYPE_STRING)) { maybeReportIssue(calculateValue(context, argumentList.last()), context, node); } } }