@Override public void visitMethod(JavaContext context, UCallExpression node, PsiMethod method) { if (context.getEvaluator().isMemberInClass(method, "android.util.Log")) { context.report(ISSUE, node, context.getLocation(node), ISSUE_DESCRIPTION); } } }
@Override public void visitReferenceExpression(PsiReferenceExpression node) { String identifier = node.getReferenceName(); boolean isLeft = LEFT_FIELD.equals(identifier); boolean isRight = RIGHT_FIELD.equals(identifier); if (!isLeft && !isRight) { return; } PsiElement resolved = node.resolve(); if (!(resolved instanceof PsiField)) { return; } else { PsiField field = (PsiField) resolved; if (!mContext.getEvaluator().isMemberInClass(field, FQCN_GRAVITY)) { return; } } String message = String.format( "Use \"`Gravity.%1$s`\" instead of \"`Gravity.%2$s`\" to ensure correct " + "behavior in right-to-left locales", (isLeft ? GRAVITY_VALUE_START : GRAVITY_VALUE_END).toUpperCase(Locale.US), (isLeft ? GRAVITY_VALUE_LEFT : GRAVITY_VALUE_RIGHT).toUpperCase(Locale.US)); PsiElement locationNode = node.getReferenceNameElement(); if (locationNode == null) { locationNode = node; } Location location = mContext.getLocation(locationNode); mContext.report(USE_START, node, location, message); } }
private static boolean isHolderConstructionMethod(@NonNull JavaContext context, @NonNull PsiMethodCallExpression callExpression) { String referenceName = callExpression.getMethodExpression().getReferenceName(); if (referenceName != null && referenceName.startsWith("of")) { PsiMethod resolved = callExpression.resolveMethod(); if (resolved != null && context.getEvaluator().isMemberInClass(resolved, "android.animation.PropertyValuesHolder")) { return true; } } return false; }
@Override public void visitReference(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiJavaCodeReferenceElement reference, @NonNull PsiElement resolved) { if (resolved instanceof PsiField && context.getEvaluator().isMemberInClass((PsiField) resolved, "android.view.MenuItem")) { if ("SHOW_AS_ACTION_ALWAYS".equals(reference.getReferenceName())) { if (context.getDriver().isSuppressed(context, ISSUE, reference)) { return; } if (mAlwaysFields == null) { mAlwaysFields = new ArrayList<>(); } mAlwaysFields.add(context.getLocation(reference)); } else { mHasIfRoomRefs = true; } } } }
&& context.getEvaluator().isMemberInClass(calledMethod, "android.content.res.TypedArray") && (call instanceof PsiMethodCallExpression)
/** Returns true if the given node is a parameter to a Logging call */ private static boolean isLoggingParameter( @NonNull JavaContext context, @NonNull PsiMethodCallExpression node) { PsiMethodCallExpression parentCall = PsiTreeUtil.getParentOfType(node, PsiMethodCallExpression.class, true); if (parentCall != null) { String name = parentCall.getMethodExpression().getReferenceName(); if (name != null && name.length() == 1) { // "d", "i", "e" etc in Log PsiMethod method = parentCall.resolveMethod(); return context.getEvaluator().isMemberInClass(method, LogDetector.LOG_CLS); } } return false; }
@NonNull PsiMethodCallExpression call, @NonNull PsiMethod method) { JavaEvaluator evaluator = context.getEvaluator(); if (!evaluator.isMemberInClass(method, "android.animation.ObjectAnimator") && !(method.getName().equals("ofPropertyValuesHolder") && evaluator.isMemberInClass(method, "android.animation.ValueAnimator"))) { return; if (!evaluator.isMemberInClass(method, "android.animation.ObjectAnimator")) {
methodName, suggested); } else if ("intersect".equals(methodName) && context.getEvaluator().isMemberInClass(method, "android.graphics.Rect")) { message += ". If the rectangles do not intersect, no change is made and the " + "original rectangle is not modified. These methods return false to "
@Override public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression call, @NonNull PsiMethod method) { if (context.getEvaluator().isMemberInClass(method, TYPE_STRING)) { String name = method.getName(); if (name.equals(FORMAT_METHOD)) { checkFormat(context, method, call); } else if (method.getParameterList().getParametersCount() == 0) { Location location = context.getNameLocation(call); String message = String.format( "Implicitly using the default locale is a common source of bugs: " + "Use `%1$s(Locale)` instead. For strings meant to be internal " + "use `Locale.ROOT`, otherwise `Locale.getDefault()`.", name); context.report(STRING_LOCALE, call, location, message); } } }
|| methodName.equals("createScaledBitmap")) { PsiMethod method = node.resolveMethod(); if (method != null && mContext.getEvaluator().isMemberInClass(method, "android.graphics.Bitmap") && !isLazilyInitialized(node)) { reportAllocation(node); if (method != null && mContext.getEvaluator().isMemberInClass(method, "android.graphics.BitmapFactory") && !isLazilyInitialized(node)) { reportAllocation(node);
@Override public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression node, @NonNull PsiMethod method) { JavaEvaluator evaluator = context.getEvaluator(); if (!evaluator.isMemberInClass(method, "android.database.sqlite.SQLiteDatabase")) { return; } int parameterCount = evaluator.getParameterCount(method); if (parameterCount == 0) { return; } if (!evaluator.parameterHasType(method, 0, TYPE_STRING)) { return; } // Try to resolve the String and look for STRING keys PsiExpression argument = node.getArgumentList().getExpressions()[0]; String sql = ConstantEvaluator.evaluateString(context, argument, true); if (sql != null && (sql.startsWith("CREATE TABLE") || sql.startsWith("ALTER TABLE")) && sql.matches(".*\\bSTRING\\b.*")) { String message = "Using column type STRING; did you mean to use TEXT? " + "(STRING is a numeric type and its value can be adjusted; for example, " + "strings that look like integers can drop leading zeroes. See issue " + "explanation for details.)"; context.report(ISSUE, node, context.getLocation(node), message); } } }
PsiMethod method = call.resolveMethod(); if (mContext.getEvaluator() .isMemberInClass(method, MOTION_EVENT_CLS)) { mEscapes = wasEscaped;
@Override public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression node, @NonNull PsiMethod method) { JavaEvaluator evaluator = context.getEvaluator(); if (evaluator.isMemberInClass(method, "android.app.AlarmManager") && evaluator.getParameterCount(method) == 4) { ensureAtLeast(context, node, 1, 5000L); ensureAtLeast(context, node, 2, 60000L); } }
@NonNull PsiMethodCallExpression node, @NonNull PsiMethod method) { JavaEvaluator evaluator = context.getEvaluator(); if (!evaluator.isMemberInClass(method, LOG_CLS)) { return;
@Override public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression call, @NonNull PsiMethod method) { if (context.getEvaluator().isMemberInClass(method, "android.util.FloatMath") && context.getProject().getMinSdk() >= 8) { String message = String.format( "Use `java.lang.Math#%1$s` instead of `android.util.FloatMath#%1$s()` " + "since it is faster as of API 8", method.getName()); PsiReferenceExpression expression = call.getMethodExpression(); PsiElement operand = expression.getQualifier(); Location location = operand != null && expression.getReferenceNameElement() != null ? context.getRangeLocation(operand, 0, expression.getReferenceNameElement(), 0) : context.getLocation(call); context.report(ISSUE, call, location, message); } } }
@Override public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression call, @NonNull PsiMethod method) { String firebaseAnalytics = "com.google.firebase.analytics.FirebaseAnalytics"; if (!context.getEvaluator().isMemberInClass(method, firebaseAnalytics)) { return; } PsiExpression[] expressions = call.getArgumentList().getExpressions(); if (expressions.length < 2) { return; } PsiElement firstArgumentExpression = expressions[0]; String value = ConstantEvaluator.evaluateString(context, firstArgumentExpression, false); if (value == null) { return; } String error = getErrorForEventName(value); if (error != null) { context.report(INVALID_NAME, call, context.getLocation(call), error); } PsiExpression secondParameter = expressions[1]; List<BundleModification> bundleModifications = getBundleModifications(context, secondParameter); if (bundleModifications != null && !bundleModifications.isEmpty()) { validateEventParameters(context, bundleModifications, call); } }
if (evaluator.isMemberInClass(method, JAVA_SECURITY_SECURE_RANDOM) || evaluator.isMemberInSubClassOf(method, JAVA_UTIL_RANDOM, false) && isSecureRandomReceiver(context, call)) {
if (!evaluator.isMemberInClass(method, WEB_VIEW_CLS)) { return;
String methodName = method.getName(); if (methodName.equals(FORMAT_METHOD)) { if (evaluator.isMemberInClass(method, TYPE_STRING)) {
@Override public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression call, @NonNull PsiMethod method) { if (!context.getEvaluator().isMemberInClass(method, "android.widget.Toast")) { return; } // Make sure you pass the right kind of duration: it's not a delay, it's // LENGTH_SHORT or LENGTH_LONG // (see http://code.google.com/p/android/issues/detail?id=3655) PsiExpression[] args = call.getArgumentList().getExpressions(); if (args.length == 3) { PsiExpression duration = args[2]; if (duration instanceof PsiLiteral) { context.report(ISSUE, duration, context.getLocation(duration), "Expected duration `Toast.LENGTH_SHORT` or `Toast.LENGTH_LONG`, a custom " + "duration value is not supported"); } } PsiMethod surroundingMethod = PsiTreeUtil.getParentOfType(call, PsiMethod.class, true); if (surroundingMethod == null) { return; } ShowFinder finder = new ShowFinder(call); surroundingMethod.accept(finder); if (!finder.isShowCalled()) { context.report(ISSUE, call, context.getLocation(call.getMethodExpression()), "Toast created but not shown: did you forget to call `show()` ?"); } }