aboutsummaryrefslogtreecommitdiffstats
path: root/lint
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-02-10 22:18:13 -0800
committerTor Norbye <tnorbye@google.com>2012-02-13 10:43:47 -0800
commit3e10306ab1812b2c141e75fb36e2f5c92eeefd28 (patch)
treea248ca617a3b0563a0c58bc8d0b09dfa4dae6166 /lint
parent71008df5a5b37666ce3142c2df69fa93391260ac (diff)
downloadsdk-3e10306ab1812b2c141e75fb36e2f5c92eeefd28.zip
sdk-3e10306ab1812b2c141e75fb36e2f5c92eeefd28.tar.gz
sdk-3e10306ab1812b2c141e75fb36e2f5c92eeefd28.tar.bz2
Make lint process Java jar dependencies
This changeset makes lint properly handle the jar dependency scope for issues. It also tweaks the API in a few minor ways. Change-Id: Ibd7b943c9d3ce361e091af8f1e990709bb94d183
Diffstat (limited to 'lint')
-rw-r--r--lint/cli/src/com/android/tools/lint/LintCliXmlParser.java13
-rw-r--r--lint/cli/src/com/android/tools/lint/LombokParser.java14
-rw-r--r--lint/cli/src/com/android/tools/lint/Main.java2
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java32
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java43
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java29
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/Location.java54
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java23
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/Scope.java3
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java2
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/StringFormatDetector.java1
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/FieldGetterDetectorTest.java15
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/bytecode/classpath-lib9
13 files changed, 218 insertions, 22 deletions
diff --git a/lint/cli/src/com/android/tools/lint/LintCliXmlParser.java b/lint/cli/src/com/android/tools/lint/LintCliXmlParser.java
index 9ee5ee8..e777e99 100644
--- a/lint/cli/src/com/android/tools/lint/LintCliXmlParser.java
+++ b/lint/cli/src/com/android/tools/lint/LintCliXmlParser.java
@@ -16,6 +16,7 @@
package com.android.tools.lint;
+import com.android.annotations.Nullable;
import com.android.tools.lint.client.api.IDomParser;
import com.android.tools.lint.client.api.IssueRegistry;
import com.android.tools.lint.detector.api.Location;
@@ -161,6 +162,7 @@ public class LintCliXmlParser extends PositionXmlParser implements IDomParser {
private class LocationHandle implements Handle {
private File mFile;
private Node mNode;
+ private Object mClientData;
public LocationHandle(File file, Node node) {
mFile = file;
@@ -176,5 +178,16 @@ public class LintCliXmlParser extends PositionXmlParser implements IDomParser {
return null;
}
+
+ @Override
+ public void setClientData(@Nullable Object clientData) {
+ mClientData = clientData;
+ }
+
+ @Override
+ @Nullable
+ public Object getClientData() {
+ return mClientData;
+ }
}
}
diff --git a/lint/cli/src/com/android/tools/lint/LombokParser.java b/lint/cli/src/com/android/tools/lint/LombokParser.java
index e1a3c3a..15b1073 100644
--- a/lint/cli/src/com/android/tools/lint/LombokParser.java
+++ b/lint/cli/src/com/android/tools/lint/LombokParser.java
@@ -16,6 +16,7 @@
package com.android.tools.lint;
+import com.android.annotations.Nullable;
import com.android.tools.lint.client.api.IJavaParser;
import com.android.tools.lint.detector.api.JavaContext;
import com.android.tools.lint.detector.api.Location;
@@ -113,6 +114,7 @@ public class LombokParser implements IJavaParser {
private class LocationHandle implements Handle {
private File mFile;
private Node mNode;
+ private Object mClientData;
public LocationHandle(File file, Node node) {
mFile = file;
@@ -124,5 +126,17 @@ public class LombokParser implements IJavaParser {
Position pos = mNode.getPosition();
return Location.create(mFile, null /*contents*/, pos.getStart(), pos.getEnd());
}
+
+
+ @Override
+ public void setClientData(@Nullable Object clientData) {
+ mClientData = clientData;
+ }
+
+ @Override
+ @Nullable
+ public Object getClientData() {
+ return mClientData;
+ }
}
}
diff --git a/lint/cli/src/com/android/tools/lint/Main.java b/lint/cli/src/com/android/tools/lint/Main.java
index d319648..3c94f93 100644
--- a/lint/cli/src/com/android/tools/lint/Main.java
+++ b/lint/cli/src/com/android/tools/lint/Main.java
@@ -797,7 +797,7 @@ public class Main extends LintClient {
}
@Override
- public void log(Throwable exception, String format, Object... args) {
+ public void log(Severity severity, Throwable exception, String format, Object... args) {
System.out.flush();
if (!mQuiet) {
// Place the error message on a line of its own since we're printing '.' etc
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java
index fb62538..48e86b5 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java
@@ -23,6 +23,7 @@ import com.android.tools.lint.detector.api.Detector;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.Project;
+import com.android.tools.lint.detector.api.Severity;
import com.google.common.annotations.Beta;
import org.w3c.dom.Document;
@@ -92,14 +93,31 @@ public abstract class LintClient {
@Nullable Object data);
/**
- * Send an exception to the log
+ * Send an exception or error message (with warning severity) to the log
*
* @param exception the exception, possibly null
* @param format the error message using {@link String#format} syntax, possibly null
* (though in that case the exception should not be null)
* @param args any arguments for the format string
*/
+ public void log(
+ @Nullable Throwable exception,
+ @Nullable String format,
+ @Nullable Object... args) {
+ log(Severity.WARNING, exception, format, args);
+ }
+
+ /**
+ * Send an exception or error message to the log
+ *
+ * @param severity the severity of the warning
+ * @param exception the exception, possibly null
+ * @param format the error message using {@link String#format} syntax, possibly null
+ * (though in that case the exception should not be null)
+ * @param args any arguments for the format string
+ */
public abstract void log(
+ @NonNull Severity severity,
@Nullable Throwable exception,
@Nullable String format,
@Nullable Object... args);
@@ -159,6 +177,7 @@ public abstract class LintClient {
/**
* Returns the list of output folders for class files
+ *
* @param project the project to look up class file locations for
* @return a list of output folders to search for .class files
*/
@@ -168,6 +187,17 @@ public abstract class LintClient {
}
/**
+ * Returns the list of Java libraries
+ *
+ * @param project the project to look up jar dependencies for
+ * @return a list of jar dependencies containing .class files
+ */
+ @NonNull
+ public List<File> getJavaLibraries(@NonNull Project project) {
+ return getEclipseClasspath(project, "lib"); //$NON-NLS-1$
+ }
+
+ /**
* Returns the {@link SdkInfo} to use for the given project.
*
* @param project the project to look up an {@link SdkInfo} for
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
index c02d735..b30d71a 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
@@ -731,11 +731,23 @@ public class LintDriver {
return;
}
+ if (mScope.contains(Scope.JAVA_LIBRARIES)) {
+ List<Detector> detectors = mScopeDetectors.get(Scope.JAVA_LIBRARIES);
+ if (detectors != null && detectors.size() > 0) {
+ List<File> libraries = project.getJavaLibraries();
+ checkClasses(project, main, libraries, detectors, true /* isLibrary */);
+ }
+ }
+
+ if (mCanceled) {
+ return;
+ }
+
if (mScope.contains(Scope.CLASS_FILE)) {
List<Detector> detectors = mScopeDetectors.get(Scope.CLASS_FILE);
if (detectors != null && detectors.size() > 0) {
- List<File> binFolders = project.getJavaClassFolders();
- checkClasses(project, main, binFolders, detectors);
+ List<File> classFolders = project.getJavaClassFolders();
+ checkClasses(project, main, classFolders, detectors, false /* isLibrary */);
}
}
@@ -789,14 +801,15 @@ public class LintDriver {
private void checkClasses(
@NonNull Project project,
@Nullable Project main,
- @NonNull List<File> binFolders,
- @NonNull List<Detector> checks) {
- if (binFolders.size() == 0) {
+ @NonNull List<File> classFolders,
+ @NonNull List<Detector> checks,
+ boolean isLibrary) {
+ if (classFolders.size() == 0) {
//mClient.log(null, "Warning: Class-file checks are enabled, but no " +
// "output folders found. Does the project need to be built first?");
}
- for (File classPathEntry : binFolders) {
+ for (File classPathEntry : classFolders) {
if (classPathEntry.getName().endsWith(DOT_JAR)) {
File jarFile = classPathEntry;
try {
@@ -810,7 +823,7 @@ public class LintDriver {
try {
File file = new File(entry.getName());
checkClassFile(b, project, main, file, jarFile, jarFile,
- checks);
+ checks, isLibrary);
} catch (Exception e) {
mClient.log(e, null);
continue;
@@ -839,7 +852,7 @@ public class LintDriver {
byte[] bytes = Files.toByteArray(file);
if (bytes != null) {
checkClassFile(bytes, project, main, file, null /*jarFile*/, binDir,
- checks);
+ checks, isLibrary);
}
} catch (IOException e) {
mClient.log(e, null);
@@ -860,7 +873,8 @@ public class LintDriver {
@NonNull File file,
@NonNull File jarFile,
@NonNull File binDir,
- @NonNull List<Detector> checks) {
+ @NonNull List<Detector> checks,
+ boolean fromLibrary) {
ClassReader reader = new ClassReader(bytes);
ClassNode classNode = new ClassNode();
reader.accept(classNode, 0 /*flags*/);
@@ -871,7 +885,7 @@ public class LintDriver {
}
ClassContext context = new ClassContext(this, project, main, file, jarFile,
- binDir, bytes, classNode);
+ binDir, bytes, classNode, fromLibrary);
for (Detector detector : checks) {
if (detector.appliesTo(context, file)) {
fireEvent(EventType.SCANNING_FILE, context);
@@ -1161,8 +1175,8 @@ public class LintDriver {
@Override
- public void log(@Nullable Throwable exception, @Nullable String format,
- @Nullable Object... args) {
+ public void log(@NonNull Severity severity, @Nullable Throwable exception,
+ @Nullable String format, @Nullable Object... args) {
mDelegate.log(exception, format, args);
}
@@ -1185,6 +1199,11 @@ public class LintDriver {
}
@Override
+ public List<File> getJavaLibraries(Project project) {
+ return mDelegate.getJavaLibraries(project);
+ }
+
+ @Override
@Nullable
public IDomParser getDomParser() {
return mDelegate.getDomParser();
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java
index 8a4fb2d..a2899d8 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java
@@ -52,21 +52,27 @@ public class ClassContext extends Context {
private boolean mSearchedForSource;
/** If the file is a relative path within a jar file, this is the jar file, otherwise null */
private final File mJarFile;
+ /** Whether this class is part of a library (rather than corresponding to one of the
+ * source files in this project */
+ private final boolean mFromLibrary;
/**
* Construct a new {@link ClassContext}
*
* @param driver the driver running through the checks
* @param project the project containing the file being checked
- * @param main the main project if this project is a library project, or null if this
- * is not a library project. The main project is the root project of all
- * library projects, not necessarily the directly including project.
+ * @param main the main project if this project is a library project, or
+ * null if this is not a library project. The main project is the
+ * root project of all library projects, not necessarily the
+ * directly including project.
* @param file the file being checked
- * @param jarFile If the file is a relative path within a jar file, this is the jar
- * file, otherwise null
+ * @param jarFile If the file is a relative path within a jar file, this is
+ * the jar file, otherwise null
* @param binDir the root binary directory containing this .class file.
* @param bytes the bytecode raw data
* @param classNode the bytecode object model
+ * @param fromLibrary whether this class is from a library rather than part
+ * of this project
*/
public ClassContext(
@NonNull LintDriver driver,
@@ -76,12 +82,14 @@ public class ClassContext extends Context {
@Nullable File jarFile,
@NonNull File binDir,
@NonNull byte[] bytes,
- @NonNull ClassNode classNode) {
+ @NonNull ClassNode classNode,
+ boolean fromLibrary) {
super(driver, project, main, file);
mJarFile = jarFile;
mBinDir = binDir;
mBytes = bytes;
mClassNode = classNode;
+ mFromLibrary = fromLibrary;
}
/**
@@ -116,6 +124,15 @@ public class ClassContext extends Context {
}
/**
+ * Returns whether this class is part of a library (not this project).
+ *
+ * @return true if this class is part of a library
+ */
+ public boolean isFromClassLibrary() {
+ return mFromLibrary;
+ }
+
+ /**
* Returns the source file for this class file, if possible.
*
* @return the source file, or null
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Location.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Location.java
index d18ab71..9d61047 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Location.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Location.java
@@ -35,6 +35,7 @@ public class Location {
private final Position mEnd;
private String mMessage;
private Location mSecondary;
+ private Object mClientData;
/**
* (Private constructor, use one of the factory methods
@@ -143,6 +144,28 @@ public class Location {
return mMessage;
}
+ /**
+ * Sets the client data associated with this location. This is an optional
+ * field which can be used by the creator of the {@link Location} to store
+ * temporary state associated with the location.
+ *
+ * @param clientData the data to store with this location
+ */
+ public void setClientData(@Nullable Object clientData) {
+ mClientData = clientData;
+ }
+
+ /**
+ * Returns the client data associated with this location - an optional field
+ * which can be used by the creator of the {@link Location} to store
+ * temporary state associated with the location.
+ *
+ * @return the data associated with this location
+ */
+ @Nullable
+ public Object getClientData() {
+ return mClientData;
+ }
@Override
public String toString() {
@@ -352,6 +375,25 @@ public class Location {
*/
@NonNull
Location resolve();
+
+ /**
+ * Sets the client data associated with this location. This is an optional
+ * field which can be used by the creator of the {@link Location} to store
+ * temporary state associated with the location.
+ *
+ * @param clientData the data to store with this location
+ */
+ public void setClientData(@Nullable Object clientData);
+
+ /**
+ * Returns the client data associated with this location - an optional field
+ * which can be used by the creator of the {@link Location} to store
+ * temporary state associated with the location.
+ *
+ * @return the data associated with this location
+ */
+ @Nullable
+ public Object getClientData();
}
/** A default {@link Handle} implementation for simple file offsets */
@@ -360,6 +402,7 @@ public class Location {
private String mContents;
private int mStartOffset;
private int mEndOffset;
+ private Object mClientData;
/**
* Constructs a new {@link DefaultLocationHandle}
@@ -380,5 +423,16 @@ public class Location {
public Location resolve() {
return Location.create(mFile, mContents, mStartOffset, mEndOffset);
}
+
+ @Override
+ public void setClientData(@Nullable Object clientData) {
+ mClientData = clientData;
+ }
+
+ @Override
+ @Nullable
+ public Object getClientData() {
+ return mClientData;
+ }
}
}
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java
index e2795ed..5146a77 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java
@@ -82,6 +82,7 @@ public class Project {
private List<File> mFiles;
private List<File> mJavaSourceFolders;
private List<File> mJavaClassFolders;
+ private List<File> mJavaLibraries;;
private List<Project> mDirectLibraries;
private List<Project> mAllLibraries;
@@ -268,6 +269,28 @@ public class Project {
}
/**
+ * Returns the list of Java libraries (typically .jar files) that this
+ * project depends on. Note that this refers to jar libraries, not Android
+ * library projects which are processed in a separate pass with their own
+ * source and class folders.
+ *
+ * @return a list of .jar files (or class folders) that this project depends
+ * on.
+ */
+ @NonNull
+ public List<File> getJavaLibraries() {
+ if (mJavaLibraries == null) {
+ // AOSP builds already merge libraries and class folders into
+ // the single classes.jar file, so these have already been processed
+ // in getJavaClassFolders.
+
+ mJavaLibraries = mClient.getJavaLibraries(this);
+ }
+
+ return mJavaLibraries;
+ }
+
+ /**
* Returns the relative path of a given file relative to the user specified
* directory (which is often the project directory but sometimes a higher up
* directory when a directory tree is being scanned
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Scope.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Scope.java
index 9e5ed81..4b9da60 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Scope.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Scope.java
@@ -77,7 +77,8 @@ public enum Scope {
PROGUARD_FILE,
/**
- * The analysis considers classes in the libraries for this project.
+ * The analysis considers classes in the libraries for this project. These
+ * will be analyzed before the classes themselves.
*/
JAVA_LIBRARIES;
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java
index 7053038..99cf76c 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java
@@ -76,7 +76,7 @@ public class ApiDetector extends LayoutDetector implements Detector.ClassScanner
6,
Severity.ERROR,
ApiDetector.class,
- EnumSet.of(Scope.CLASS_FILE, Scope.JAVA_LIBRARIES, Scope.RESOURCE_FILE));
+ EnumSet.of(Scope.CLASS_FILE, Scope.RESOURCE_FILE));
private ApiLookup mApiDatabase;
private int mMinApi = -1;
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/StringFormatDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/StringFormatDetector.java
index 4d1c8ae..ac3a7a3 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/StringFormatDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/StringFormatDetector.java
@@ -149,6 +149,7 @@ public class StringFormatDetector extends ResourceXmlDetector implements Detecto
* defined multiple times, usually for different translations.
*/
private Map<String, List<Pair<Handle, String>>> mFormatStrings;
+
/**
* List of strings that contain percents that aren't formatting strings; these
* should not be passed to String.format.
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/FieldGetterDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/FieldGetterDetectorTest.java
index bdb7618..ccbf26b 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/FieldGetterDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/FieldGetterDetectorTest.java
@@ -41,6 +41,21 @@ public class FieldGetterDetectorTest extends AbstractCheckTest {
));
}
+ public void testLibraries() throws Exception {
+ // This tests the infrastructure: it makes sure that we *don't* run this
+ // check in jars that are on the jar library dependency path (testJar() checks
+ // that it *does* work for local jar classes)
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "bytecode/classpath-lib=>.classpath",
+ "bytecode/AndroidManifest.xml=>AndroidManifest.xml",
+ "bytecode/GetterTest.java.txt=>src/test/bytecode/GetterTest.java",
+ "bytecode/GetterTest.jar.data=>libs/library.jar"
+ ));
+ }
+
public void testJar() throws Exception {
assertEquals(
"GetterTest.java:47: Warning: Calling getter method getFoo1() on self is slower than field access (mFoo1)\n" +
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/bytecode/classpath-lib b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/bytecode/classpath-lib
new file mode 100644
index 0000000..e730df8
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/bytecode/classpath-lib
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="lib" path="libs/library.jar"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>