@Override public boolean isGradleProject() { return mocker != null || super.isGradleProject(); }
@Override public void beforeCheckFile(@NonNull Context context) { mHasLeanbackLauncherActivity = false; mHasLeanbackSupport = false; mHasApplicationBanner = false; mLeanbackActivitiesWithoutBanners = 0; mUnsupportedHardwareImpliedPermissions = Lists.newArrayListWithExpectedSize(2); mUnsupportedTvUsesFeatures = Sets.newHashSetWithExpectedSize(2); mAllUnsupportedTvUsesFeatures = Sets.newHashSetWithExpectedSize(2); // Check gradle dependency Project mainProject = context.getMainProject(); mHasLeanbackDependency = (mainProject.isGradleProject() && Boolean.TRUE.equals(mainProject.dependsOn(LEANBACK_LIB_ARTIFACT))); }
private static void checkCustomNamespace(XmlContext context, Element element) { NamedNodeMap attributes = element.getAttributes(); for (int i = 0, n = attributes.getLength(); i < n; i++) { Attr attribute = (Attr) attributes.item(i); if (attribute.getName().startsWith(XMLNS_PREFIX)) { String uri = attribute.getValue(); if (uri != null && !uri.isEmpty() && uri.startsWith(URI_PREFIX) && !(uri.equals(ANDROID_URI) || uri.equals(AMAZON_URI) || uri.equals(EUCLID_URI))) { // AMAZON_EDIT_ONELINE if (context.getProject().isGradleProject()) { context.report(RES_AUTO, attribute, context.getValueLocation(attribute), "In Gradle projects, always use `" + AUTO_URI + "` for custom " + "attributes"); } else { context.report(CUSTOM_VIEW, attribute, context.getValueLocation(attribute), "When using a custom namespace attribute in a library project, " + "use the namespace `\"" + AUTO_URI + "\"` instead."); } } } } }
private static void checkCustomNamespace(XmlContext context, Element element) { NamedNodeMap attributes = element.getAttributes(); for (int i = 0, n = attributes.getLength(); i < n; i++) { Attr attribute = (Attr) attributes.item(i); if (attribute.getName().startsWith(XMLNS_PREFIX)) { String uri = attribute.getValue(); if (uri != null && !uri.isEmpty() && uri.startsWith(URI_PREFIX) && !uri.equals(ANDROID_URI)) { if (context.getProject().isGradleProject()) { context.report(RES_AUTO, attribute, context.getValueLocation(attribute), "In Gradle projects, always use `" + AUTO_URI + "` for custom " + "attributes"); } else { context.report(CUSTOM_VIEW, attribute, context.getValueLocation(attribute), "When using a custom namespace attribute in a library project, " + "use the namespace `\"" + AUTO_URI + "\"` instead."); } } } } }
@Nullable private static String computeResourcePrefix(@NonNull Project project) { if (project.isGradleProject()) { return LintUtils.computeResourcePrefix(project.getGradleProjectModel()); } return null; }
private static boolean isPrivate(Context context, ResourceType type, String name) { if (context.getProject().isGradleProject()) { ResourceVisibilityLookup lookup = context.getProject().getResourceVisibility(); return lookup.isPrivate(type, name); } return false; }
@Nullable private static String computeResourcePrefix(@NonNull Project project) { if (project.isGradleProject()) { return LintUtils.computeResourcePrefix(project.getGradleProjectModel()); } return null; }
/** Returns true iff the given manifest file is the main manifest file */ private static boolean isMainManifest(XmlContext context, File manifestFile) { if (!context.getProject().isGradleProject()) { // In non-gradle projects, just one manifest per project return true; } AndroidProject model = context.getProject().getGradleProjectModel(); return model == null || manifestFile .equals(model.getDefaultConfig().getSourceProvider().getManifestFile()); }
/** Returns true iff the given manifest file is the main manifest file */ private static boolean isMainManifest(XmlContext context, File manifestFile) { if (!context.getProject().isGradleProject()) { // In non-gradle projects, just one manifest per project return true; } AndroidProject model = context.getProject().getGradleProjectModel(); return model == null || manifestFile .equals(model.getDefaultConfig().getSourceProvider().getManifestFile()); }
private static boolean isPrivate(Context context, ResourceType type, String name) { if (type == ResourceType.ID) { // No need to complain about "overriding" id's. There's no harm // in doing so. (This avoids warning about cases like for example // appcompat's (private) @id/title resource, which would otherwise // flag any attempt to create a resource named title in the user's // project. return false; } if (context.getProject().isGradleProject()) { ResourceVisibilityLookup lookup = context.getProject().getResourceVisibility(); return lookup.isPrivate(type, name); } return false; }
/** * If this is a Gradle project with a valid Gradle model, return the version * of the model/plugin. * * @return the Gradle plugin version, or null if invalid or not a Gradle project */ @Nullable public GradleVersion getGradleModelVersion() { if (gradleVersion == null && isGradleProject()) { AndroidProject gradleProjectModel = getGradleProjectModel(); if (gradleProjectModel != null) { gradleVersion = GradleVersion.tryParse(gradleProjectModel.getModelVersion()); } } return gradleVersion; }
@Nullable public static Dependencies getCompileDependencies(@NonNull Project project) { if (!project.isGradleProject()) { return null; } Variant variant = project.getCurrentVariant(); if (variant == null) { return null; } AndroidArtifact artifact = variant.getMainArtifact(); return artifact.getDependencies(); } }
@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."); } }
/** Check resource references: accessing a private resource from an upstream library? */ @Override public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) { String value = attribute.getNodeValue(); if (context.getProject().isGradleProject()) { ResourceUrl url = ResourceUrl.parse(value); if (isPrivate(context, url)) { String message = createUsageErrorMessage(context, url.type, url.name); context.report(ISSUE, attribute, context.getValueLocation(attribute), message); } } }
/** Check resource references: accessing a private resource from an upstream library? */ @Override public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) { String value = attribute.getNodeValue(); if (context.getProject().isGradleProject()) { ResourceUrl url = ResourceUrl.parse(value); if (isPrivate(context, url)) { String message = createUsageErrorMessage(context, url.type, url.name); context.report(ISSUE, attribute, context.getValueLocation(attribute), message); } } }
@Nullable private static List<String> getResConfigLanguages(@NonNull Project project) { if (project.isGradleProject() && project.getGradleProjectModel() != null && project.getCurrentVariant() != null) { Set<String> relevantDensities = Sets.newHashSet(); Variant variant = project.getCurrentVariant(); List<String> variantFlavors = variant.getProductFlavors(); AndroidProject gradleProjectModel = project.getGradleProjectModel(); addResConfigsFromFlavor(relevantDensities, null, project.getGradleProjectModel().getDefaultConfig()); for (ProductFlavorContainer container : gradleProjectModel.getProductFlavors()) { addResConfigsFromFlavor(relevantDensities, variantFlavors, container); } if (!relevantDensities.isEmpty()) { ArrayList<String> strings = Lists.newArrayList(relevantDensities); Collections.sort(strings); return strings; } } return null; }
@Nullable private static List<String> getResConfigLanguages(@NonNull Project project) { if (project.isGradleProject() && project.getGradleProjectModel() != null && project.getCurrentVariant() != null) { Set<String> relevantDensities = Sets.newHashSet(); Variant variant = project.getCurrentVariant(); List<String> variantFlavors = variant.getProductFlavors(); AndroidProject gradleProjectModel = project.getGradleProjectModel(); addResConfigsFromFlavor(relevantDensities, null, project.getGradleProjectModel().getDefaultConfig()); for (ProductFlavorContainer container : gradleProjectModel.getProductFlavors()) { addResConfigsFromFlavor(relevantDensities, variantFlavors, container); } if (!relevantDensities.isEmpty()) { ArrayList<String> strings = Lists.newArrayList(relevantDensities); Collections.sort(strings); return strings; } } return null; }
@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; } }
@Override public void beforeCheckProject(@NonNull Context context) { mHasNativeLibs = false; mApplicationTagHandle = null; if (!context.getMainProject().isGradleProject() || context.getMainProject().getGradleModelVersion() == null) { mSuppress = true; return; } //compileSdkVersion must be >= 23 boolean projectSupportsAttribute = context.getMainProject().getBuildSdk() >= 23; //android gradle plugin must be 2.2.0+ GradleVersion gradleVersion = context.getMainProject().getGradleModelVersion(); boolean gradleSupportsAttribute = MIN_GRADLE_VERSION.compareIgnoringQualifiers(gradleVersion) <= 0; //suppress lint check if the compile SDK or the Gradle plugin are too old mSuppress = !projectSupportsAttribute || !gradleSupportsAttribute; }
@Override public void visitResourceReference( @NonNull JavaContext context, @Nullable AstVisitor visitor, @NonNull Node node, @NonNull String type, @NonNull String name, boolean isFramework) { if (context.getProject().isGradleProject() && !isFramework) { Project project = context.getProject(); if (project.getGradleProjectModel() != null && project.getCurrentVariant() != null) { ResourceType resourceType = ResourceType.getEnum(type); if (resourceType != null && isPrivate(context, resourceType, name)) { String message = createUsageErrorMessage(context, resourceType, name); context.report(ISSUE, node, context.getLocation(node), message); } } } }