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 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; }
ResolvedClass containingClass = method.getContainingClass(); if ((OBTAIN.equals(name) || OBTAIN_NO_HISTORY.equals(name)) && containingClass.isSubclassOf(MOTION_EVENT_CLS, false)) { checkRecycled(context, node, MOTION_EVENT_CLS, RECYCLE); } else if (OBTAIN.equals(name) && containingClass.isSubclassOf(PARCEL_CLS, false)) { checkRecycled(context, node, PARCEL_CLS, RECYCLE); } else if (OBTAIN.equals(name) && containingClass.isSubclassOf(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)) && (containingClass.isSubclassOf(CLASS_CONTEXT, false) || containingClass.isSubclassOf(RESOURCES_CLS, false))) { TypeDescriptor returnType = method.getReturnType(); if (returnType != null && returnType.matchesSignature(TYPED_ARRAY_CLS)) { checkRecycled(context, node, TYPED_ARRAY_CLS, RECYCLE); } else if (ACQUIRE_CPC.equals(name) && containingClass.isSubclassOf( CONTENT_RESOLVER_CLS, false)) { checkRecycled(context, node, CONTENT_PROVIDER_CLIENT_CLS, RELEASE); || QUERY_WITH_FACTORY.equals(name) || RAW_QUERY_WITH_FACTORY.equals(name)) && (containingClass.isSubclassOf(SQLITE_DATABASE_CLS, false) || containingClass.isSubclassOf(CONTENT_RESOLVER_CLS, false) || containingClass.isSubclassOf(CONTENT_PROVIDER_CLS, false) || containingClass.isSubclassOf(CONTENT_PROVIDER_CLIENT_CLS, false))) {
if (resolvedClass.isSubclassOf(CLASS_VIEW, false)) { if (!styleableName.equals(className)) { String message = String.format( context.report(ISSUE, node, context.getLocation(expression), message); } else if (resolvedClass.isSubclassOf(CLASS_VIEWGROUP + DOT_LAYOUT_PARAMS, false)) { ClassDeclaration outer = JavaContext.findSurroundingClass(cls.getParent()); if (outer == null) {
ResolvedMethod method = (ResolvedMethod) resolved; JavaParser.ResolvedClass clz = method.getContainingClass(); if (clz.isSubclassOf("android.content.SharedPreferences.Editor", false) && mContext.getProject().getMinSdkVersion().getApiLevel() >= 9) {
if (!method.getContainingClass().isSubclassOf(CLASS_VIEW, false)) { return null; if (!method.getContainingClass().isSubclassOf( "android.support.wearable.watchface.WatchFaceService.Engine", false)) { return null;
if (r instanceof ResolvedClass) { ResolvedClass parcelable = (ResolvedClass) r; if (!parcelable.isSubclassOf("android.os.Parcelable", false)) { return true;
if (clzz.isSubclassOf(sSupportSuperType[i], false)) { isSubClass = true; break;
if (!method.getContainingClass().isSubclassOf(CIPHER, false)) { return;
@Override protected boolean isCleanupCall(@NonNull MethodInvocation call) { String methodName = call.astName().astValue(); if (!recycleName.equals(methodName)) { return false; } ResolvedNode resolved = mContext.resolve(call); if (resolved instanceof ResolvedMethod) { ResolvedClass containingClass = ((ResolvedMethod) resolved).getContainingClass(); if (containingClass.isSubclassOf(recycleType, false)) { // Yes, called the right recycle() method; now make sure // we're calling it on the right variable Expression operand = call.astOperand(); if (operand != null) { resolved = mContext.resolve(operand); //noinspection SuspiciousMethodCalls if (resolved != null && mVariables.contains(resolved)) { return true; } } } } return false; } };
/** * Returns true if the given method invocation node corresponds to a call on a * {@code android.content.Context} * * @param node the method call node * @return true iff the method call is on a class extending context * @deprecated use {@link JavaEvaluator#isMemberInSubClassOf(PsiMember, String, boolean)} instead */ @Deprecated public boolean isContextMethod(@NonNull MethodInvocation node) { // Method name used in many other contexts where it doesn't have the // same semantics; only use this one if we can resolve types // and we're certain this is the Context method ResolvedNode resolved = resolve(node); if (resolved instanceof JavaParser.ResolvedMethod) { JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) resolved; ResolvedClass containingClass = method.getContainingClass(); if (containingClass.isSubclassOf(CLASS_CONTEXT, false)) { return true; } } return false; }
@Override public void visitMethod(@NonNull JavaContext context, @Nullable AstVisitor visitor, @NonNull MethodInvocation node) { // Ignore the issue if we never build for any API less than 17. if (context.getMainProject().getMinSdk() >= 17) { return; } // Ignore if the method doesn't fit our description. ResolvedNode resolved = context.resolve(node); if (!(resolved instanceof ResolvedMethod)) { return; } ResolvedMethod method = (ResolvedMethod) resolved; if (!method.getContainingClass().isSubclassOf(WEB_VIEW, false)) { return; } if (method.getArgumentCount() != 2 || !method.getArgumentType(0).matchesName(TYPE_OBJECT) || !method.getArgumentType(1).matchesName(TYPE_STRING)) { return; } String message = "`WebView.addJavascriptInterface` should not be called with minSdkVersion < 17 for security reasons: " + "JavaScript can use reflection to manipulate application"; context.report(ISSUE, node, context.getLocation(node.astName()), message); } }
@Override public void checkClass(@NonNull JavaContext context, @Nullable ClassDeclaration node, @NonNull Node declarationOrAnonymous, @NonNull ResolvedClass resolvedClass) { if (!context.getProject().getReportIssues()) { return; } String className = resolvedClass.getName(); if (resolvedClass.isSubclassOf(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(resolvedClass)) { return; } String message = String.format( "`PreferenceActivity` subclass `%1$s` should not be exported", className); context.report(ISSUE, mExportedActivities.get(className).resolve(), message); } }
private static boolean isAppBarActivityCall(@NonNull JavaContext context, @NonNull MethodInvocation node) { ResolvedNode resolved = context.resolve(node); if (resolved instanceof ResolvedMethod) { ResolvedMethod method = (ResolvedMethod) resolved; ResolvedClass containingClass = method.getContainingClass(); if (containingClass.isSubclassOf(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) ClassDeclaration surroundingClass = JavaContext.findSurroundingClass(node); if (surroundingClass != null) { ResolvedNode clz = context.resolve(surroundingClass); return clz instanceof ResolvedClass && ((ResolvedClass)clz).isSubclassOf( "android.support.v7.app.ActionBarActivity", false); } } } return false; }
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; }
@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); } } }
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; }
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 }