private static boolean isLeakCandidate( @NonNull PsiClass cls, @NonNull JavaEvaluator evaluator) { return evaluator.extendsClass(cls, CLASS_CONTEXT, false) || evaluator.extendsClass(cls, CLASS_VIEW, false) || evaluator.extendsClass(cls, CLASS_FRAGMENT, false); } }
private static boolean isBeginTransaction(@NonNull JavaContext context, @NonNull PsiMethod method) { String methodName = method.getName(); if (BEGIN_TRANSACTION.equals(methodName)) { PsiClass containingClass = method.getContainingClass(); JavaEvaluator evaluator = context.getEvaluator(); if (evaluator.extendsClass(containingClass, FRAGMENT_MANAGER_CLS, false) || evaluator.extendsClass(containingClass, FRAGMENT_MANAGER_V4_CLS, false)) { return true; } } return false; }
/** * Checks whether the class extends a super class or implements a given interface. Like calling * both {@link #extendsClass(PsiClass, String, boolean)} and {@link * #implementsInterface(PsiClass, String, boolean)}. */ public boolean inheritsFrom( @NonNull PsiClass cls, @NonNull String className, boolean strict) { return extendsClass(cls, className, strict) || implementsInterface(cls, className, strict); }
private static String getTag(@NonNull JavaEvaluator evaluator, @NonNull PsiClass cls) { String tag = null; for (String s : sClasses) { if (evaluator.extendsClass(cls, s, false)) { tag = classToTag(s); break; } } return tag; }
public boolean isMemberInSubClassOf( @NonNull PsiMember method, @NonNull String className, boolean strict) { PsiClass containingClass = method.getContainingClass(); return containingClass != null && extendsClass(containingClass, className, strict); }
evaluator.extendsClass(containingClass, MOTION_EVENT_CLS, false)) { checkRecycled(context, node, MOTION_EVENT_CLS, RECYCLE); } else if (OBTAIN.equals(name) && evaluator.extendsClass(containingClass, PARCEL_CLS, false)) { checkRecycled(context, node, PARCEL_CLS, RECYCLE); } else if (OBTAIN.equals(name) && evaluator.extendsClass(containingClass, VELOCITY_TRACKER_CLS, false)) { checkRecycled(context, node, VELOCITY_TRACKER_CLS, RECYCLE); } else if ((OBTAIN_STYLED_ATTRIBUTES.equals(name) || OBTAIN_ATTRIBUTES.equals(name) || OBTAIN_TYPED_ARRAY.equals(name)) && (evaluator.extendsClass(containingClass, CLASS_CONTEXT, false) || evaluator.extendsClass(containingClass, SdkConstants.CLASS_RESOURCES, false))) { PsiType returnType = method.getReturnType(); if (returnType instanceof PsiClassType) { } else if (ACQUIRE_CPC.equals(name) && evaluator.extendsClass(containingClass, CONTENT_RESOLVER_CLS, false)) { checkRecycled(context, node, CONTENT_PROVIDER_CLIENT_CLS, RELEASE); || QUERY_WITH_FACTORY.equals(name) || RAW_QUERY_WITH_FACTORY.equals(name)) && (evaluator.extendsClass(containingClass, SQLITE_DATABASE_CLS, false) || evaluator.extendsClass(containingClass, CONTENT_RESOLVER_CLS, false) || evaluator.extendsClass(containingClass, CLASS_CONTENTPROVIDER, false) || evaluator.extendsClass(containingClass, CONTENT_PROVIDER_CLIENT_CLS, false))) {
private static boolean isSharedEditorCreation(@NonNull JavaContext context, @NonNull PsiMethod method) { String methodName = method.getName(); if (EDIT.equals(methodName)) { PsiClass containingClass = method.getContainingClass(); JavaEvaluator evaluator = context.getEvaluator(); return evaluator.extendsClass(containingClass, ANDROID_CONTENT_SHARED_PREFERENCES, false); } return false; }
private static boolean isMethodOnFragmentClass( @NonNull JavaContext context, @NonNull PsiMethodCallExpression call, @NonNull String fragmentClass, @NonNull String v4FragmentClass, boolean returnForUnresolved) { PsiMethod method = call.resolveMethod(); if (method != null) { PsiClass containingClass = method.getContainingClass(); JavaEvaluator evaluator = context.getEvaluator(); return evaluator.extendsClass(containingClass, fragmentClass, false) || evaluator.extendsClass(containingClass, v4FragmentClass, false); } else { // If we *can't* resolve the method call, caller can decide // whether to consider the method called or not return returnForUnresolved; } }
private static boolean isEditorApplyMethodCall(@NonNull JavaContext context, @NonNull PsiMethodCallExpression call) { String methodName = call.getMethodExpression().getReferenceName(); if (APPLY.equals(methodName)) { PsiMethod method = call.resolveMethod(); if (method != null) { PsiClass containingClass = method.getContainingClass(); JavaEvaluator evaluator = context.getEvaluator(); return evaluator.extendsClass(containingClass, ANDROID_CONTENT_SHARED_PREFERENCES_EDITOR, false); } } return false; }
@Override public void checkClass(@NonNull JavaContext context, @NonNull PsiClass declaration) { if (declaration.getName() == null) { return; } // In case linting the base class itself. if (!context.getEvaluator().extendsClass(declaration, CLASS_ACTIVITY, true)) { return; } declaration.accept(new MethodVisitor(context, declaration)); }
private static boolean isAppBarActivityCall(@NonNull JavaContext context, @NonNull PsiMethodCallExpression node, @NonNull PsiMethod method) { JavaEvaluator evaluator = context.getEvaluator(); if (evaluator.isMemberInSubClassOf(method, CLASS_ACTIVITY, false)) { // Make sure that the calling context is a subclass of ActionBarActivity; // we don't want to flag these calls if they are in non-appcompat activities // such as PreferenceActivity (see b.android.com/58512) PsiClass cls = PsiTreeUtil.getParentOfType(node, PsiClass.class, true); return cls != null && evaluator.extendsClass(cls, "android.support.v7.app.ActionBarActivity", false); } return false; }
@Override public void checkClass(@NonNull JavaContext context, @NonNull PsiClass declaration) { if (!context.getProject().getReportIssues()) { return; } JavaEvaluator evaluator = context.getEvaluator(); String className = declaration.getQualifiedName(); if (evaluator.extendsClass(declaration, PREFERENCE_ACTIVITY, false) && mExportedActivities.containsKey(className)) { // Ignore the issue if we target an API greater than 19 and the class in // question specifically overrides isValidFragment() and thus knowingly white-lists // valid fragments. if (context.getMainProject().getTargetSdk() >= 19 && overridesIsValidFragment(evaluator, declaration)) { return; } String message = String.format( "`PreferenceActivity` subclass `%1$s` should not be exported", className); Location location = mExportedActivities.get(className).resolve(); context.report(ISSUE, declaration, location, message); } }
@Override protected boolean isCleanupCall(@NonNull PsiMethodCallExpression call) { PsiReferenceExpression methodExpression = call.getMethodExpression(); String methodName = methodExpression.getReferenceName(); if (!recycleName.equals(methodName)) { return false; } PsiMethod method = call.resolveMethod(); if (method != null) { PsiClass containingClass = method.getContainingClass(); if (mContext.getEvaluator().extendsClass(containingClass, recycleType, false)) { // Yes, called the right recycle() method; now make sure // we're calling it on the right variable PsiExpression operand = methodExpression.getQualifierExpression(); if (operand instanceof PsiReferenceExpression) { PsiElement resolved = ((PsiReferenceExpression) operand).resolve(); //noinspection SuspiciousMethodCalls if (resolved != null && mVariables.contains(resolved)) { return true; } } } } return false; } };
private static boolean isEditorCommitMethodCall(@NonNull JavaContext context, @NonNull PsiMethodCallExpression call) { String methodName = call.getMethodExpression().getReferenceName(); if (COMMIT.equals(methodName)) { PsiMethod method = call.resolveMethod(); if (method != null) { PsiClass containingClass = method.getContainingClass(); JavaEvaluator evaluator = context.getEvaluator(); if (evaluator.extendsClass(containingClass, ANDROID_CONTENT_SHARED_PREFERENCES_EDITOR, false)) { suggestApplyIfApplicable(context, call); return true; } } } return false; }
@Override public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression call, @NonNull PsiMethod method) { if (context.getEvaluator().isMemberInSubClassOf(method, SSL_CERTIFICATE_SOCKET_FACTORY_CLASS, false)) { String methodName = method.getName(); if ("createSocket".equals(methodName)) { PsiExpression[] args = call.getArgumentList().getExpressions(); if (args.length > 0) { PsiType type = args[0].getType(); if (type != null && (INET_ADDRESS_CLASS.equals(type.getCanonicalText()) || context.getEvaluator().extendsClass(((PsiClassType)type).resolve(), INET_ADDRESS_CLASS, false))) { context.report(CREATE_SOCKET, call, context.getLocation(call), "Use of `SSLCertificateSocketFactory.createSocket()` " + "with an InetAddress parameter can cause insecure " + "network traffic due to trusting arbitrary hostnames in " + "TLS/SSL certificates presented by peers"); } } } else if ("getInsecure".equals(methodName)) { context.report(GET_INSECURE, call, context.getLocation(call), "Use of `SSLCertificateSocketFactory.getInsecure()` can cause " + "insecure network traffic due to trusting arbitrary TLS/SSL " + "certificates presented by peers"); } } } }
if (framework == null) { reportMissing(context, cls, className, rightTag); } else if (!evaluator.extendsClass(cls, framework, false)) { reportWrongTag(context, cls, rightTag, className, framework);
/** * Given a context type (of a parameter or field), check to see if that type implies * that the context is not the application context (for example because it's an Activity * rather than a plain context). * <p> * Returns true if it finds and reports a problem. */ private static boolean checkWifiContextType(@NonNull JavaContext context, @NonNull PsiMethodCallExpression call, @NonNull PsiType type, boolean flagPlainContext) { JavaEvaluator evaluator = context.getEvaluator(); if (type instanceof PsiClassType) { PsiClass psiClass = ((PsiClassType) type).resolve(); if (evaluator.extendsClass(psiClass, CLASS_APPLICATION, false)) { return false; } } if (evaluator.typeMatches(type, CLASS_CONTEXT)) { if (flagPlainContext) { reportWifiServiceLeak(WIFI_MANAGER_UNCERTAIN, context, call); return true; } return false; } reportWifiServiceLeak(WIFI_MANAGER, context, call); return true; }
if (context.getEvaluator().extendsClass(cls, CLASS_VIEW, false)) { if (!styleableName.equals(className)) { String message = String.format( context.report(ISSUE, node, context.getLocation(expression), message); } else if (context.getEvaluator().extendsClass(cls, CLASS_VIEWGROUP + DOT_LAYOUT_PARAMS, false)) { PsiClass outer = PsiTreeUtil.getParentOfType(cls, PsiClass.class, true);
if (evaluator.extendsClass(typeClass, CLASS_VIEW, false)) { objectType = "views"; } else if (evaluator.implementsInterface(typeClass, CURSOR_CLS, false)) {