aboutsummaryrefslogtreecommitdiffstats
path: root/lint/libs/lint_api
diff options
context:
space:
mode:
Diffstat (limited to 'lint/libs/lint_api')
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java17
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java40
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java28
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java9
4 files changed, 86 insertions, 8 deletions
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 93e311e..4cca31c 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
@@ -33,6 +33,7 @@ import com.android.tools.lint.detector.api.Project;
import com.android.tools.lint.detector.api.Severity;
import com.google.common.annotations.Beta;
import com.google.common.collect.Maps;
+import com.google.common.io.Files;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -177,6 +178,22 @@ public abstract class LintClient {
public abstract String readFile(@NonNull File file);
/**
+ * Reads the given binary file and returns the content as a byte array.
+ * By default this method will read the bytes from the file directly,
+ * but this can be customized by a client if for example I/O could be
+ * held in memory and not flushed to disk yet.
+ *
+ * @param file the file to read
+ * @return the bytes in the file, never null
+ * @throws IOException if the file does not exist, or if the file cannot be
+ * read for some reason
+ */
+ @NonNull
+ public byte[] readBytes(@NonNull File file) throws IOException {
+ return Files.toByteArray(file);
+ }
+
+ /**
* Returns the list of source folders for Java source files
*
* @param project the project to look up Java source file locations 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 270ffa4..d91b155 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
@@ -55,7 +55,6 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
-import com.google.common.io.Files;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
@@ -1023,7 +1022,7 @@ public class LintDriver {
String path = file.getPath();
if (file.isFile() && path.endsWith(DOT_CLASS)) {
try {
- byte[] bytes = Files.toByteArray(file);
+ byte[] bytes = mClient.readBytes(file);
if (bytes != null) {
for (File dir : classFolders) {
if (path.startsWith(dir.getPath())) {
@@ -1068,6 +1067,8 @@ public class LintDriver {
if (classDetectors != null && classDetectors.size() > 0 && entries.size() > 0) {
AsmVisitor visitor = new AsmVisitor(mClient, classDetectors);
+ String sourceContents = null;
+ String sourceName = "";
mOuterClasses = new ArrayDeque<ClassNode>();
for (ClassEntry entry : entries) {
ClassReader reader;
@@ -1097,9 +1098,31 @@ public class LintDriver {
continue;
}
+ if (sourceContents != null) {
+ // Attempt to reuse the source buffer if initialized
+ // This means making sure that the source files
+ // foo/bar/MyClass and foo/bar/MyClass$Bar
+ // and foo/bar/MyClass$3 and foo/bar/MyClass$3$1 have the same prefix.
+ String newName = classNode.name;
+ int newRootLength = newName.indexOf('$');
+ if (newRootLength == -1) {
+ newRootLength = newName.length();
+ }
+ int oldRootLength = sourceName.indexOf('$');
+ if (oldRootLength == -1) {
+ oldRootLength = sourceName.length();
+ }
+ if (newRootLength != oldRootLength ||
+ !sourceName.regionMatches(0, newName, 0, newRootLength)) {
+ sourceContents = null;
+ }
+ }
+
ClassContext context = new ClassContext(this, project, main,
entry.file, entry.jarFile, entry.binDir, entry.bytes,
- classNode, scope == Scope.JAVA_LIBRARIES /*fromLibrary*/);
+ classNode, scope == Scope.JAVA_LIBRARIES /*fromLibrary*/,
+ sourceContents);
+
try {
visitor.runClassDetectors(context);
} catch (Exception e) {
@@ -1109,6 +1132,9 @@ public class LintDriver {
if (mCanceled) {
return;
}
+
+ sourceContents = context.getSourceContents(false/*read*/);
+ sourceName = classNode.name;
}
mOuterClasses = null;
@@ -1229,7 +1255,7 @@ public class LintDriver {
for (File file : classFiles) {
try {
- byte[] bytes = Files.toByteArray(file);
+ byte[] bytes = mClient.readBytes(file);
if (bytes != null) {
entries.add(new ClassEntry(file, null /* jarFile*/, binDir, bytes));
}
@@ -1568,6 +1594,12 @@ public class LintDriver {
@Override
@NonNull
+ public byte[] readBytes(@NonNull File file) throws IOException {
+ return mDelegate.readBytes(file);
+ }
+
+ @Override
+ @NonNull
public List<File> getJavaSourceFolders(@NonNull Project project) {
return mDelegate.getJavaSourceFolders(project);
}
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 4aa21d4..5f8cac9 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
@@ -82,6 +82,8 @@ public class ClassContext extends Context {
* @param classNode the bytecode object model
* @param fromLibrary whether this class is from a library rather than part
* of this project
+ * @param sourceContents initial contents of the Java source, if known, or
+ * null
*/
public ClassContext(
@NonNull LintDriver driver,
@@ -92,13 +94,15 @@ public class ClassContext extends Context {
@NonNull File binDir,
@NonNull byte[] bytes,
@NonNull ClassNode classNode,
- boolean fromLibrary) {
+ boolean fromLibrary,
+ @Nullable String sourceContents) {
super(driver, project, main, file);
mJarFile = jarFile;
mBinDir = binDir;
mBytes = bytes;
mClassNode = classNode;
mFromLibrary = fromLibrary;
+ mSourceContents = sourceContents;
}
/**
@@ -217,6 +221,28 @@ public class ClassContext extends Context {
}
/**
+ * Returns the contents of the source file for this class file, if found. If
+ * {@code read} is false, do not read the source contents if it has not
+ * already been read. (This is primarily intended for the lint
+ * infrastructure; most client code would call {@link #getSourceContents()}
+ * .)
+ *
+ * @param read whether to read the source contents if it has not already
+ * been initialized
+ * @return the source contents, which will never be null if {@code read} is
+ * true, or null if {@code read} is false and the source contents
+ * hasn't already been read.
+ */
+ @Nullable
+ public String getSourceContents(boolean read) {
+ if (read) {
+ return getSourceContents();
+ } else {
+ return mSourceContents;
+ }
+ }
+
+ /**
* Returns a location for the given source line number in this class file's
* source file, if available.
*
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java
index 9bfb7cc..ce64fe3 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java
@@ -27,9 +27,9 @@ import com.android.annotations.Nullable;
import com.android.resources.FolderTypeRelationship;
import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
+import com.android.tools.lint.client.api.LintClient;
import com.android.util.PositionXmlParser;
import com.google.common.annotations.Beta;
-import com.google.common.io.Files;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
@@ -394,13 +394,16 @@ public class LintUtils {
* same as {@code Files.toString(file, Charsets.UTF8}, but if there's a UTF byte order mark
* (for UTF8, UTF_16 or UTF_16LE), use that instead.
*
+ * @param client the client to use for I/O operations
* @param file the file to read from
* @return the string
* @throws IOException if the file cannot be read properly
*/
@NonNull
- public static String getEncodedString(@NonNull File file) throws IOException {
- byte[] bytes = Files.toByteArray(file);
+ public static String getEncodedString(
+ @NonNull LintClient client,
+ @NonNull File file) throws IOException {
+ byte[] bytes = client.readBytes(file);
if (endsWith(file.getName(), DOT_XML)) {
return PositionXmlParser.getXmlString(bytes);
}