@Nullable @Override public JavaElementVisitor createPsiVisitor(@NonNull final JavaContext context) { if (!context.getMainProject().isAndroidProject()) { return null;
PsiType first = types[0]; String typeName = first.getCanonicalText(); int minSdk = mContext.getMainProject().getMinSdk(); if (TYPE_INTEGER_WRAPPER.equals(typeName) || TYPE_BYTE_WRAPPER.equals(typeName)) { String valueType = types[1].getCanonicalText(); Boolean.TRUE == mContext.getMainProject().dependsOn( SUPPORT_LIB_ARTIFACT))) { boolean useBuiltin = minSdk >= 16;
private PermissionHolder getPermissions( @NonNull JavaContext context) { if (mPermissions == null) { Set<String> permissions = Sets.newHashSetWithExpectedSize(30); Set<String> revocable = Sets.newHashSetWithExpectedSize(4); LintClient client = context.getClient(); // Gather permissions from all projects that contribute to the // main project. Project mainProject = context.getMainProject(); for (File manifest : mainProject.getManifestFiles()) { addPermissions(client, permissions, revocable, manifest); } for (Project library : mainProject.getAllLibraries()) { for (File manifest : library.getManifestFiles()) { addPermissions(client, permissions, revocable, manifest); } } mPermissions = new SetPermissionLookup(permissions, revocable); } return mPermissions; }
@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 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); } }
TypeReference first = types.first(); String typeName = first.getTypeName(); int minSdk = mContext.getMainProject().getMinSdk(); if (typeName.equals(INTEGER) || typeName.equals(BYTE)) { String valueType = types.last().getTypeName(); Boolean.TRUE == mContext.getMainProject().dependsOn( SUPPORT_LIB_ARTIFACT))) { boolean useBuiltin = minSdk >= 16;
@Override public boolean visitAssert(Assert node) { if (!context.getMainProject().isAndroidProject()) { return true; } Expression assertion = node.astAssertion(); // Allow "assert true"; it's basically a no-op if (assertion instanceof BooleanLiteral) { Boolean b = ((BooleanLiteral) assertion).astValue(); if (b != null && b) { return false; } } else { // Allow assertions of the form "assert foo != null" because they are often used // to make statements to tools about known nullness properties. For example, // findViewById() may technically return null in some cases, but a developer // may know that it won't be when it's called correctly, so the assertion helps // to clear nullness warnings. if (isNullCheck(assertion)) { return false; } } String message = "Assertions are unreliable. Use `BuildConfig.DEBUG` conditional checks instead."; context.report(ISSUE, node, context.getLocation(node), message); return false; } };
private PermissionHolder getPermissions( @NonNull JavaContext context) { if (mPermissions == null) { Set<String> permissions = Sets.newHashSetWithExpectedSize(30); Set<String> revocable = Sets.newHashSetWithExpectedSize(4); LintClient client = context.getClient(); // Gather permissions from all projects that contribute to the // main project. Project mainProject = context.getMainProject(); for (File manifest : mainProject.getManifestFiles()) { addPermissions(client, permissions, revocable, manifest); } for (Project library : mainProject.getAllLibraries()) { for (File manifest : library.getManifestFiles()) { addPermissions(client, permissions, revocable, manifest); } } AndroidVersion minSdkVersion = mainProject.getMinSdkVersion(); AndroidVersion targetSdkVersion = mainProject.getTargetSdkVersion(); mPermissions = new SetPermissionLookup(permissions, revocable, minSdkVersion, targetSdkVersion); } return mPermissions; }
@SuppressWarnings("SpellCheckingInspection") private static boolean isMinifying(@NonNull JavaContext context) { Project project = context.getMainProject(); if (!project.isGradleProject()) { // Not a Gradle project: assume project may be using ProGuard/other shrinking return true; } AndroidProject model = project.getGradleProjectModel(); if (model != null) { for (BuildTypeContainer buildTypeContainer : model.getBuildTypes()) { if (buildTypeContainer.getBuildType().isMinifyEnabled()) { return true; } } } else { // No model? Err on the side of caution. return true; } return false; } }
private static void reportWifiServiceLeak(@NonNull Issue issue, @NonNull JavaContext context, @NonNull PsiMethodCallExpression call) { if (context.getMainProject().getMinSdk() >= 24) { // Bug is fixed in Nougat return; } String qualifier = ""; if (call.getMethodExpression().getQualifierExpression() != null) { qualifier = call.getMethodExpression().getQualifierExpression().getText(); } String message = String.format("The WIFI_SERVICE must be looked up on the " + "Application context or memory will leak on devices < Android N. " + "Try changing `%1$s` to `%1$s.getApplicationContext()` ", qualifier); context.report(issue, call, context.getLocation(call), message); }
.getProjectResources(context.getMainProject(), true); if (resources == null) { return;
@Override public void checkClass(@NonNull JavaContext context, @NonNull PsiClass declaration) { Project project = context.getMainProject(); if (project.dependsOn(APPCOMPAT_LIB_ARTIFACT) != Boolean.TRUE) { return; } PsiClass superClass = declaration.getSuperClass(); if (!hasAppCompatDelegate(context, superClass)) { return; } PsiElement locationNode = declaration; PsiReferenceList extendsList = declaration.getExtendsList(); if (extendsList != null) { PsiJavaCodeReferenceElement[] elements = extendsList.getReferenceElements(); if (elements.length > 0) { locationNode = elements[0]; } } Location location = context.getNameLocation(locationNode); String suggested = getAppCompatDelegate(superClass); // Keep error message in sync with #getSuggestedSuperClass below String message = String.format("This custom view should extend `%1$s` instead", suggested); context.report(ISSUE, declaration, location, message); }
@Override public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression node, @NonNull PsiMethod method) { // Ignore the issue if we never build for any API less than 17. if (context.getMainProject().getMinSdk() >= 17) { return; } JavaEvaluator evaluator = context.getEvaluator(); if (!evaluator.methodMatches(method, WEB_VIEW, true, TYPE_OBJECT, 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.getNameLocation(node), message); } }
@Override public void visitReference(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiJavaCodeReferenceElement reference, @NonNull PsiElement resolved) { if (resolved instanceof PsiField && context.getEvaluator().isMemberInSubClassOf((PsiField)resolved, "android.provider.Settings", false) && context.getMainProject().getTargetSdkVersion().getFeatureLevel() >= 23) { String message = getBatteryOptimizationsErrorMessage(); context.report(ISSUE, reference, context.getNameLocation(reference), message); } }
String pkgName = pkg.getQualifiedName(); if (!(pkgName.equals(context.getProject().getPackage()) || pkgName.equals(context.getMainProject().getPackage()))) { foreignPackage = true; context.getClient().getResourceRepository(context.getMainProject(), true, false); if (repository != null && repository.hasResourceItem(resourceType, name)) { return;
if (context.getMainProject().getMinSdk() >= 14) { return;
@Override public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression call, @NonNull PsiMethod method) { if (context.getMainProject().getTargetSdk() < 17) { return;
@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); } }
@Nullable AstVisitor visitor, @NonNull MethodInvocation call) { if (context.getMainProject().getTargetSdk() < 17) { return;
context.getMainProject().getTargetSdkVersion().getFeatureLevel() >= 23 && requirement.getLastApplicableApi() >= 23) {