@Override public void visitResourceReference( @NonNull JavaContext context, @Nullable AstVisitor visitor, @NonNull Node select, @NonNull String type, @NonNull String name, boolean isFramework) { if (type.equals(RESOURCE_CLZ_COLOR)) { while (select.getParent() instanceof Select) { select = select.getParent(); } Node current = select.getParent(); while (current != null) { if (current.getClass() == MethodInvocation.class) { MethodInvocation call = (MethodInvocation) current; String methodName = call.astName().astValue(); if (methodName.endsWith("Color") // $NON-NLS-1$ && methodName.startsWith("set")) { // $NON-NLS-1$ if ("setProgressBackgroundColor".equals(methodName)) { // Special exception: SwipeRefreshLayout does not follow the normal // naming convention: its setProgressBackgroundColor does *not* take // an ARGB color integer, it takes a resource id. // This method name is unique across the framework and support // libraries. return; } context.report( ISSUE, select, context.getLocation(select), String.format( "Should pass resolved color instead of resource id here: " + "`getResources().getColor(%1$s)`", select.toString())); } break; } else if (current.getClass() == MethodDeclaration.class) { break; } current = current.getParent(); } } }
@Override public boolean visitStringLiteral(StringLiteral node) { String s = node.astValue(); // Other potential String prefixes to check for: // /mnt/sdcard/ // /system/media/sdcard // file://sdcard // file:///sdcard if (s.startsWith("/sdcard")) { // $NON-NLS-1$ String message = "Do not hardcode \"/sdcard/\"; " + "use Environment.getExternalStorageDirectory().getPath() instead"; Location location = mContext.getLocation(node); mContext.report(ISSUE, node, location, message, s); } return false; }