@Override public void afterCheckProject(@NonNull Context context) { if (mFormatStrings != null) { boolean checkCount = context.isEnabled(ARG_COUNT); boolean checkValid = context.isEnabled(INVALID); boolean checkTypes = context.isEnabled(ARG_TYPES); // Ensure that all the format strings are consistent with respect to each other; // e.g. they all have the same number of arguments, they all use all the // arguments, and they all use the same types for all the numbered arguments for (Map.Entry<String, List<Pair<Handle, String>>> entry : mFormatStrings.entrySet()) { String name = entry.getKey(); List<Pair<Handle, String>> list = entry.getValue(); // Check argument counts if (checkCount) { checkArity(context, name, list); } // Check argument types (and also make sure that the formatting strings are valid) if (checkValid || checkTypes) { checkTypes(context, checkValid, checkTypes, name, list); } } } }
@Override public void afterCheckProject(@NonNull Context context) { if (mFormatStrings != null) { boolean checkCount = context.isEnabled(ARG_COUNT); boolean checkValid = context.isEnabled(INVALID); boolean checkTypes = context.isEnabled(ARG_TYPES); // Ensure that all the format strings are consistent with respect to each other; // e.g. they all have the same number of arguments, they all use all the // arguments, and they all use the same types for all the numbered arguments for (Map.Entry<String, List<Pair<Handle, String>>> entry : mFormatStrings.entrySet()) { String name = entry.getKey(); List<Pair<Handle, String>> list = entry.getValue(); // Check argument counts if (checkCount) { Handle notFormatted = mNotFormatStrings.get(name); if (notFormatted != null) { list = ImmutableList.<Pair<Handle, String>>builder() .add(Pair.of(notFormatted, name)).addAll(list).build(); } checkArity(context, name, list); } // Check argument types (and also make sure that the formatting strings are valid) if (checkValid || checkTypes) { checkTypes(context, checkValid, checkTypes, name, list); } } } }
protected void checkOctal( @NonNull Context context, @NonNull String value, @NonNull Object cookie) { if (value.length() >= 2 && value.charAt(0) == '0' && (value.length() > 2 || value.charAt(1) >= '8' && isInteger(value)) && context.isEnabled(ACCIDENTAL_OCTAL)) { String message = "The leading 0 turns this number into octal which is probably " + "not what was intended"; try { long numericValue = Long.decode(value); message += " (interpreted as " + numericValue + ")"; } catch (NumberFormatException nufe) { message += " (and it is not a valid octal number)"; } report(context, cookie, ACCIDENTAL_OCTAL, message); } }
protected void checkOctal( @NonNull Context context, @NonNull String value, @NonNull Object cookie) { if (value.length() >= 2 && value.charAt(0) == '0' && (value.length() > 2 || value.charAt(1) >= '8' && isInteger(value)) && context.isEnabled(ACCIDENTAL_OCTAL)) { String message = "The leading 0 turns this number into octal which is probably " + "not what was intended"; try { long numericValue = Long.decode(value); message += " (interpreted as " + numericValue + ")"; } catch (NumberFormatException nufe) { message += " (and it is not a valid octal number)"; } report(context, cookie, ACCIDENTAL_OCTAL, message); } }
private void checkLocalMavenVersions(Context context, GradleCoordinate dependency, Object cookie, String groupId, String artifactId, File repository) { GradleCoordinate max = SdkMavenRepository.getHighestInstalledVersion(groupId, artifactId, repository, null, false); if (max != null) { if (COMPARE_PLUS_HIGHER.compare(dependency, max) < 0 && context.isEnabled(DEPENDENCY)) { String message = getNewerVersionAvailableMessage(dependency, max.getFullRevision()); report(context, cookie, DEPENDENCY, message); } } }
private void checkLocalMavenVersions(Context context, GradleCoordinate dependency, Object cookie, String groupId, String artifactId, File repository) { GradleCoordinate max = MavenRepositories.getHighestInstalledVersion( groupId, artifactId, repository, null, false, FileOpUtils.create()); if (max != null) { if (COMPARE_PLUS_HIGHER.compare(dependency, max) < 0 && context.isEnabled(DEPENDENCY)) { String message = getNewerVersionAvailableMessage(dependency, max.getRevision()); report(context, cookie, DEPENDENCY, message); } } }
@Override public void afterCheckFile(@NonNull Context context) { XmlContext xmlContext = (XmlContext) context; Element element = xmlContext.document.getDocumentElement(); if (element != null) { checkDocumentElement(xmlContext, element); } if (mSeenUsesSdk == 0 && context.isEnabled(USES_SDK) // Not required in Gradle projects; typically defined in build.gradle instead // and inserted at build time && !context.getMainProject().isGradleProject()) { context.report(USES_SDK, Location.create(context.file), "Manifest should specify a minimum API level with " + "`<uses-sdk android:minSdkVersion=\"?\" />`; if it really supports " + "all versions of Android set it to 1."); } }
@Override public void afterCheckFile(@NonNull Context context) { XmlContext xmlContext = (XmlContext) context; Element element = xmlContext.document.getDocumentElement(); if (element != null) { checkDocumentElement(xmlContext, element); } if (mSeenUsesSdk == 0 && context.isEnabled(USES_SDK) // Not required in Gradle projects; typically defined in build.gradle instead // and inserted at build time && !context.getMainProject().isGradleProject()) { context.report(USES_SDK, Location.create(context.file), "Manifest should specify a minimum API level with " + "`<uses-sdk android:minSdkVersion=\"?\" />`; if it really supports " + "all versions of Android set it to 1."); } /** AMAZON_EDIT_BEGIN */ if (mSeenUsesAmznSdk == 0 && context.isEnabled(USES_AMZN_SDK) && isAmznBuildTarget(xmlContext)) { context.report(USES_AMZN_SDK, Location.create(context.file), "Manifest should specify a minimum API level with " + "`<uses-amzn-sdk android:minSdkVersion=\"?\" />`; if it really supports " + "all versions of Fire OS set it to 1.", null); } /** AMAZON_EDIT_END */ }
@Override public void afterCheckProject(@NonNull Context context) { if (!mSeenAllowBackup && context.isEnabled(ALLOW_BACKUP) && !context.getProject().isLibrary() && context.getMainProject().getMinSdk() >= 4) { Location location = getMainApplicationTagLocation(context); context.report(ALLOW_BACKUP, location, "Should explicitly set `android:allowBackup` to `true` or " + "`false` (it's `true` by default, and that can have some security " + "implications for the application's data)"); } if (!context.getMainProject().isLibrary() && !mSeenAppIcon && context.isEnabled(APPLICATION_ICON)) { Location location = getMainApplicationTagLocation(context); context.report(APPLICATION_ICON, location, "Should explicitly set `android:icon`, there is no default"); } }
@Override public void afterCheckProject(@NonNull Context context) { if (!mSeenAllowBackup && context.isEnabled(ALLOW_BACKUP) && !context.getProject().isLibrary() && context.getMainProject().getMinSdk() >= 4) { Location location = getMainApplicationTagLocation(context); context.report(ALLOW_BACKUP, location, "Should explicitly set `android:allowBackup` to `true` or " + "`false` (it's `true` by default, and that can have some security " + "implications for the application's data)"); } if (!context.getMainProject().isLibrary() && !mSeenAppIcon && context.isEnabled(APPLICATION_ICON)) { Location location = getMainApplicationTagLocation(context); context.report(APPLICATION_ICON, location, "Should explicitly set `android:icon`, there is no default"); } }
if (context.isEnabled(CROSS_LAYOUT) && context.getScope().contains(Scope.ALL_RESOURCE_FILES)) { IncludeGraph graph = new IncludeGraph(context);
if (context.isEnabled(CROSS_LAYOUT) && context.getScope().contains(Scope.ALL_RESOURCE_FILES)) { IncludeGraph graph = new IncludeGraph(context);
&& dependency.getMajorVersion() != mCompileSdkVersion && dependency.getMajorVersion() != GradleCoordinate.PLUS_REV_VALUE && context.isEnabled(COMPATIBILITY)) { String message = "This support library should not use a different version (" + dependency.getMajorVersion() + ") than the `compileSdkVersion` (" && dependency.getMajorVersion() < mTargetSdkVersion && dependency.getMajorVersion() != GradleCoordinate.PLUS_REV_VALUE && context.isEnabled(COMPATIBILITY)) { String message = "This support library should not use a lower version (" + dependency.getMajorVersion() + ") than the `targetSdkVersion` ("
private void report(@NonNull Context context, @NonNull Object cookie, @NonNull Issue issue, @NonNull String message) { if (context.isEnabled(issue)) { // Suppressed? // Temporarily unconditionally checking for suppress comments in Gradle files // since Studio insists on an AndroidLint id prefix boolean checkComments = /*context.getClient().checkForSuppressComments() &&*/ context.containsCommentSuppress(); if (checkComments) { int startOffset = getStartOffset(context, cookie); if (startOffset >= 0 && context.isSuppressedWithComment(startOffset, issue)) { return; } } context.report(issue, createLocation(context, cookie), message); } }
private void report(@NonNull Context context, @NonNull Object cookie, @NonNull Issue issue, @NonNull String message) { if (context.isEnabled(issue)) { // Suppressed? // Temporarily unconditionally checking for suppress comments in Gradle files // since Studio insists on an AndroidLint id prefix boolean checkComments = /*context.getClient().checkForSuppressComments() &&*/ context.containsCommentSuppress(); if (checkComments) { int startOffset = getStartOffset(context, cookie); if (startOffset >= 0 && context.isSuppressedWithComment(startOffset, issue)) { return; } } context.report(issue, createLocation(context, cookie), message); } }
private void checkSupportLibraries(Context context, GradleCoordinate dependency, Object cookie) { String groupId = dependency.getGroupId(); String artifactId = dependency.getArtifactId(); assert groupId != null && artifactId != null; // See if the support library version is lower than the targetSdkVersion if (mTargetSdkVersion > 0 && dependency.getMajorVersion() < mTargetSdkVersion && dependency.getMajorVersion() != GradleCoordinate.PLUS_REV_VALUE && // The multidex library doesn't follow normal supportlib numbering scheme !dependency.getArtifactId().startsWith("multidex") && context.isEnabled(COMPATIBILITY)) { String message = "This support library should not use a lower version (" + dependency.getMajorVersion() + ") than the `targetSdkVersion` (" + mTargetSdkVersion + ")"; report(context, cookie, COMPATIBILITY, message); } // Check to make sure you have the Android support repository installed File sdkHome = context.getClient().getSdkHome(); File repository = SdkMavenRepository.ANDROID.getRepositoryLocation(sdkHome, true); if (repository == null) { report(context, cookie, DEPENDENCY, "Dependency on a support library, but the SDK installation does not " + "have the \"Extras > Android Support Repository\" installed. " + "Open the SDK manager and install it."); } else { checkLocalMavenVersions(context, dependency, cookie, groupId, artifactId, repository); } }
@NonNull @Override protected Project createProject(@NonNull File dir, @NonNull File referenceDir) { Project project = super.createProject(dir, referenceDir); if (project.isGradleProject()) { @SuppressWarnings("SpellCheckingInspection") String message = String.format("\"`%1$s`\" is a Gradle project. To correctly " + "analyze Gradle projects, you should run \"`gradlew :lint`\" instead.", project.getName()); Location location = Location.create(project.getDir()); Context context = new Context(driver, project, project, project.getDir()); if (context.isEnabled(IssueRegistry.LINT_ERROR) && !getConfiguration(project, null).isIgnored(context, IssueRegistry.LINT_ERROR, location, message)) { report(context, IssueRegistry.LINT_ERROR, project.getConfiguration(null).getSeverity( IssueRegistry.LINT_ERROR), location, message, TextFormat.RAW); } } return project; }