com.android.tools.lint.detector.api.Scope Maven / Gradle / Ivy
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.lint.detector.api;
import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
import static com.android.SdkConstants.DOT_CLASS;
import static com.android.SdkConstants.DOT_GRADLE;
import static com.android.SdkConstants.DOT_JAVA;
import static com.android.SdkConstants.DOT_PNG;
import static com.android.SdkConstants.DOT_PROPERTIES;
import static com.android.SdkConstants.DOT_XML;
import static com.android.SdkConstants.FN_PROJECT_PROGUARD_FILE;
import static com.android.SdkConstants.OLD_PROGUARD_FILE;
import static com.android.SdkConstants.RES_FOLDER;
import com.android.annotations.NonNull;
import com.google.common.annotations.Beta;
import java.io.File;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
/**
* The scope of a detector is the set of files a detector must consider when
* performing its analysis. This can be used to determine when issues are
* potentially obsolete, whether a detector should re-run on a file save, etc.
*
* NOTE: This is not a public or final API; if you rely on this be prepared
* to adjust your code for the next tools release.
*/
@Beta
public enum Scope {
/**
* The analysis only considers a single XML resource file at a time.
*
* Issues which are only affected by a single resource file can be checked
* for incrementally when a file is edited.
*/
RESOURCE_FILE,
/**
* The analysis only considers a single binary (typically a bitmap) resource file at a time.
*
* Issues which are only affected by a single resource file can be checked
* for incrementally when a file is edited.
*/
BINARY_RESOURCE_FILE,
/**
* The analysis considers the resource folders
*/
RESOURCE_FOLDER,
/**
* The analysis considers all the resource file. This scope must not
* be used in conjunction with {@link #RESOURCE_FILE}; an issue scope is
* either considering just a single resource file or all the resources, not
* both.
*/
ALL_RESOURCE_FILES,
/**
* The analysis only considers a single Java source file at a time.
*
* Issues which are only affected by a single Java source file can be
* checked for incrementally when a Java source file is edited.
*/
JAVA_FILE,
/**
* The analysis considers all the Java source files together.
*
* This flag is mutually exclusive with {@link #JAVA_FILE}.
*/
ALL_JAVA_FILES,
/**
* The analysis only considers a single Java class file at a time.
*
* Issues which are only affected by a single Java class file can be checked
* for incrementally when a Java source file is edited and then recompiled.
*/
CLASS_FILE,
/**
* The analysis considers all the Java class files together.
*
* This flag is mutually exclusive with {@link #CLASS_FILE}.
*/
ALL_CLASS_FILES,
/** The analysis considers the manifest file */
MANIFEST,
/** The analysis considers the Proguard configuration file */
PROGUARD_FILE,
/**
* The analysis considers classes in the libraries for this project. These
* will be analyzed before the classes themselves.
*/
JAVA_LIBRARIES,
/** The analysis considers a Gradle build file */
GRADLE_FILE,
/** The analysis considers Java property files */
PROPERTY_FILE,
/**
* Scope for other files. Issues that specify a custom scope will be called unconditionally.
* This will call {@link Detector#run(Context)}} on the detectors unconditionally.
*/
OTHER;
/**
* Returns true if the given scope set corresponds to scanning a single file
* rather than a whole project
*
* @param scopes the scope set to check
* @return true if the scope set references a single file
*/
public static boolean checkSingleFile(@NonNull EnumSet scopes) {
int size = scopes.size();
if (size == 2) {
// When single checking a Java source file, we check both its Java source
// and the associated class files
return scopes.contains(JAVA_FILE) && scopes.contains(CLASS_FILE);
} else {
return size == 1 &&
(scopes.contains(JAVA_FILE)
|| scopes.contains(CLASS_FILE)
|| scopes.contains(RESOURCE_FILE)
|| scopes.contains(PROGUARD_FILE)
|| scopes.contains(PROPERTY_FILE)
|| scopes.contains(GRADLE_FILE)
|| scopes.contains(MANIFEST));
}
}
/**
* Returns the intersection of two scope sets
*
* @param scope1 the first set to intersect
* @param scope2 the second set to intersect
* @return the intersection of the two sets
*/
@NonNull
public static EnumSet intersect(
@NonNull EnumSet scope1,
@NonNull EnumSet scope2) {
EnumSet scope = EnumSet.copyOf(scope1);
scope.retainAll(scope2);
return scope;
}
/**
* Infers a suitable scope to use from the given projects to be analyzed
* @param projects the projects to find a suitable scope for
* @return the scope to use
*/
@NonNull
public static EnumSet infer(@NonNull Collection projects) {
// Infer the scope
EnumSet scope = EnumSet.noneOf(Scope.class);
for (Project project : projects) {
List subset = project.getSubset();
if (subset != null) {
for (File file : subset) {
String name = file.getName();
if (name.equals(ANDROID_MANIFEST_XML)) {
scope.add(MANIFEST);
} else if (name.endsWith(DOT_XML)) {
scope.add(RESOURCE_FILE);
} else if (name.endsWith(DOT_JAVA)) {
scope.add(JAVA_FILE);
} else if (name.endsWith(DOT_CLASS)) {
scope.add(CLASS_FILE);
} else if (name.endsWith(DOT_GRADLE)) {
scope.add(GRADLE_FILE);
} else if (name.equals(OLD_PROGUARD_FILE)
|| name.equals(FN_PROJECT_PROGUARD_FILE)) {
scope.add(PROGUARD_FILE);
} else if (name.endsWith(DOT_PROPERTIES)) {
scope.add(PROPERTY_FILE);
} else if (name.endsWith(DOT_PNG)) {
scope.add(BINARY_RESOURCE_FILE);
} else if (name.equals(RES_FOLDER)
|| file.getParent().equals(RES_FOLDER)) {
scope.add(ALL_RESOURCE_FILES);
scope.add(RESOURCE_FILE);
scope.add(BINARY_RESOURCE_FILE);
scope.add(RESOURCE_FOLDER);
}
}
} else {
// Specified a full project: just use the full project scope
scope = Scope.ALL;
break;
}
}
return scope;
}
/** All scopes: running lint on a project will check these scopes */
public static final EnumSet ALL = EnumSet.allOf(Scope.class);
/** Scope-set used for detectors which are affected by a single resource file */
public static final EnumSet RESOURCE_FILE_SCOPE = EnumSet.of(RESOURCE_FILE);
/** Scope-set used for detectors which are affected by a single resource folder */
public static final EnumSet RESOURCE_FOLDER_SCOPE = EnumSet.of(RESOURCE_FOLDER);
/** Scope-set used for detectors which scan all resources */
public static final EnumSet ALL_RESOURCES_SCOPE = EnumSet.of(ALL_RESOURCE_FILES);
/** Scope-set used for detectors which are affected by a single Java source file */
public static final EnumSet JAVA_FILE_SCOPE = EnumSet.of(JAVA_FILE);
/** Scope-set used for detectors which are affected by a single Java class file */
public static final EnumSet CLASS_FILE_SCOPE = EnumSet.of(CLASS_FILE);
/** Scope-set used for detectors which are affected by a single Gradle build file */
public static final EnumSet GRADLE_SCOPE = EnumSet.of(GRADLE_FILE);
/** Scope-set used for detectors which are affected by the manifest only */
public static final EnumSet MANIFEST_SCOPE = EnumSet.of(MANIFEST);
/** Scope-set used for detectors which correspond to some other context */
public static final EnumSet OTHER_SCOPE = EnumSet.of(OTHER);
/** Scope-set used for detectors which are affected by a single ProGuard class file */
public static final EnumSet PROGUARD_SCOPE = EnumSet.of(PROGUARD_FILE);
/** Scope-set used for detectors which correspond to property files */
public static final EnumSet PROPERTY_SCOPE = EnumSet.of(PROPERTY_FILE);
/** Resource XML files and manifest files */
public static final EnumSet MANIFEST_AND_RESOURCE_SCOPE =
EnumSet.of(Scope.MANIFEST, Scope.RESOURCE_FILE);
/** Scope-set used for detectors which are affected by single XML and Java source files */
public static final EnumSet JAVA_AND_RESOURCE_FILES =
EnumSet.of(RESOURCE_FILE, JAVA_FILE);
/** Scope-set used for analyzing individual class files and all resource files */
public static final EnumSet CLASS_AND_ALL_RESOURCE_FILES =
EnumSet.of(ALL_RESOURCE_FILES, CLASS_FILE);
/** Scope-set used for analyzing all class files, including those in libraries */
public static final EnumSet ALL_CLASSES_AND_LIBRARIES =
EnumSet.of(Scope.ALL_CLASS_FILES, Scope.JAVA_LIBRARIES);
/** Scope-set used for detectors which are affected by Java libraries */
public static final EnumSet JAVA_LIBRARY_SCOPE = EnumSet.of(JAVA_LIBRARIES);
/** Scope-set used for detectors which are affected by a single binary resource file */
public static final EnumSet BINARY_RESOURCE_FILE_SCOPE =
EnumSet.of(BINARY_RESOURCE_FILE);
}