aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-03-06 17:50:42 -0800
committerTor Norbye <tnorbye@google.com>2012-03-06 17:50:42 -0800
commit9a654c3e45ec87e29d0644ab6fb3c830fa73e5ba (patch)
treeb144195ee457671ec3b9d077b11bc9a4d530c462
parentcd3617b0c4d32a23f0dbe71cfaed40fdba5f9865 (diff)
downloadsdk-9a654c3e45ec87e29d0644ab6fb3c830fa73e5ba.zip
sdk-9a654c3e45ec87e29d0644ab6fb3c830fa73e5ba.tar.gz
sdk-9a654c3e45ec87e29d0644ab6fb3c830fa73e5ba.tar.bz2
Misc Lint Fixes
This changeset contains fixes for several unrelated reported lint bugs: 26505: Default disabled rules that are explicitly enabled do not activate 26467: Lint says ByteBuffer.array is API 9+ but it's really API 1+ 26501: Warning "This tag and its children can be replaced by one <TextView/> and a compound drawable" is not always correct (Partially fixed) It also fixes the following bugs: - The quickfix for the typography detector did not work for the fraction warning (replacing 1/2 with the half unicode symbol etc) - A couple of XML detectors did not check for SuppressLint on the associated root node - Add a --exitcode flag, and only set the exit code to non-zero if that flag is specified. Also fix the code such that non-fatal errors also contribute to the exit code. - Make the HTML reporter classes public to help Maven integration. Change-Id: I60f5fdcb2a465d51fa58bb918a195b373096d54b
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoringTest.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5-expected-7.xml9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.info3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.xml18
-rw-r--r--lint/cli/src/com/android/tools/lint/HtmlReporter.java20
-rw-r--r--lint/cli/src/com/android/tools/lint/Main.java47
-rw-r--r--lint/cli/src/com/android/tools/lint/MultiProjectHtmlReporter.java6
-rw-r--r--lint/cli/src/com/android/tools/lint/Reporter.java31
-rw-r--r--lint/cli/src/com/android/tools/lint/TextReporter.java21
-rw-r--r--lint/cli/src/com/android/tools/lint/XmlReporter.java18
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiClass.java48
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiLookup.java32
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java2
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/TypographyDetector.java14
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/UseCompoundDrawableDetector.java7
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiLookupTest.java5
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java7
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/compound2.xml17
19 files changed, 269 insertions, 53 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java
index 0480cda..53b8f49 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java
@@ -56,6 +56,7 @@ import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
@@ -283,6 +284,17 @@ public class UseCompoundDrawableRefactoring extends VisualRefactoring {
setAndroidAttribute(newTextElement, androidNsPrefix, drawableAttribute, src);
+ // If the removed LinearLayout is the root container, transfer its namespace
+ // declaration to the TextView
+ if (layout.getParentNode() instanceof Document) {
+ List<Attr> declarations = findNamespaceAttributes(layout);
+ for (Attr attribute : declarations) {
+ if (attribute instanceof IndexedRegion) {
+ newTextElement.setAttribute(attribute.getName(), attribute.getValue());
+ }
+ }
+ }
+
// Update any layout references to the layout to point to the text view
String layoutId = getId(layout);
if (layoutId.length() > 0) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoringTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoringTest.java
index 04b9b1a..c1a5ca4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoringTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoringTest.java
@@ -57,6 +57,11 @@ public class UseCompoundDrawableRefactoringTest extends RefactoringTest {
checkRefactoring("refactoring/usecompound/compound_all.xml", "@+id/layout3");
}
+ public void test7() throws Exception {
+ // Test converting where a namespace needs to be migrated
+ checkRefactoring("refactoring/usecompound/compound5.xml", "@+id/layout");
+ }
+
private void checkRefactoring(String basename, String id) throws Exception {
IFile file = getLayoutFile(getProject(), basename);
TestContext info = setupTestContext(file, basename);
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5-expected-7.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5-expected-7.xml
new file mode 100644
index 0000000..e909811
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5-expected-7.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/TextView1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawableBottom="@drawable/ic_launcher"
+ android:text="Hello World" >
+
+</TextView> \ No newline at end of file
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.info b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.info
new file mode 100644
index 0000000..8eb5c4b
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.info
@@ -0,0 +1,3 @@
+android.widget.LinearLayout [0,74,480,800] <LinearLayout>
+ android.widget.TextView [0,0,107,26] <TextView>
+ android.widget.ImageView [0,26,72,98] <ImageView>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.xml
new file mode 100644
index 0000000..49c0594
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/layout"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Hello World" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_launcher" />
+
+</LinearLayout>
diff --git a/lint/cli/src/com/android/tools/lint/HtmlReporter.java b/lint/cli/src/com/android/tools/lint/HtmlReporter.java
index 9cc9c6f..8b3e99e 100644
--- a/lint/cli/src/com/android/tools/lint/HtmlReporter.java
+++ b/lint/cli/src/com/android/tools/lint/HtmlReporter.java
@@ -28,6 +28,7 @@ import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.Position;
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.base.Charsets;
import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
@@ -51,8 +52,12 @@ import java.util.Set;
/**
* A reporter which emits lint results into an HTML report.
+ * <p>
+ * <b>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.</b>
*/
-class HtmlReporter extends Reporter {
+@Beta
+public class HtmlReporter extends Reporter {
private static boolean USE_HOLO_STYLE = true;
private static final String CSS = USE_HOLO_STYLE
? "hololike.css" : "default.css"; //$NON-NLS-1$ //$NON-NLS-2$
@@ -72,13 +77,20 @@ class HtmlReporter extends Reporter {
private String mStripPrefix;
private String mFixUrl;
- HtmlReporter(Main client, File output) throws IOException {
+ /**
+ * Creates a new {@link HtmlReporter}
+ *
+ * @param client the associated client
+ * @param output the output file
+ * @throws IOException if an error occurs
+ */
+ public HtmlReporter(Main client, File output) throws IOException {
super(client, output);
mWriter = new BufferedWriter(new FileWriter(output));
}
@Override
- void write(int errorCount, int warningCount, List<Warning> issues) throws IOException {
+ public void write(int errorCount, int warningCount, List<Warning> issues) throws IOException {
Map<Issue, String> missing = computeMissingIssues(issues);
mWriter.write(
@@ -406,7 +418,7 @@ class HtmlReporter extends Reporter {
continue;
}
- if (!issue.isEnabledByDefault()) {
+ if (!issue.isEnabledByDefault() && !mClient.isAllEnabled()) {
map.put(issue, "Default");
continue;
}
diff --git a/lint/cli/src/com/android/tools/lint/Main.java b/lint/cli/src/com/android/tools/lint/Main.java
index 1f2191b..6a40cb3 100644
--- a/lint/cli/src/com/android/tools/lint/Main.java
+++ b/lint/cli/src/com/android/tools/lint/Main.java
@@ -78,6 +78,7 @@ public class Main extends LintClient {
private static final String ARG_CONFIG = "--config"; //$NON-NLS-1$
private static final String ARG_URL = "--url"; //$NON-NLS-1$
private static final String ARG_VERSION = "--version"; //$NON-NLS-1$
+ private static final String ARG_EXITCODE = "--exitcode"; //$NON-NLS-1$
private static final String ARG_NOWARN2 = "--nowarn"; //$NON-NLS-1$
// GCC style flag names for options
@@ -100,7 +101,8 @@ public class Main extends LintClient {
private Set<String> mEnabled = new HashSet<String>();
/** If non-null, only run the specified checks (possibly modified by enable/disables) */
private Set<String> mCheck = null;
- private boolean mFatal;
+ private boolean mHasErrors;
+ private boolean mSetExitCode;
private boolean mFullPath;
private int mErrorCount;
private int mWarningCount;
@@ -228,6 +230,8 @@ public class Main extends LintClient {
mQuiet = true;
} else if (arg.equals(ARG_NOLINES)) {
mShowLines = false;
+ } else if (arg.equals(ARG_EXITCODE)) {
+ mSetExitCode = true;
} else if (arg.equals(ARG_VERSION)) {
printVersion();
System.exit(0);
@@ -489,7 +493,7 @@ public class Main extends LintClient {
System.exit(ERRNO_INVALIDARGS);
}
- System.exit(mFatal ? ERRNO_ERRORS : 0);
+ System.exit(mSetExitCode ? (mHasErrors ? ERRNO_ERRORS : 0) : 0);
}
/**
@@ -805,8 +809,10 @@ public class Main extends LintClient {
ARG_HELP + " <topic>", "Help on the given topic, such as \"suppress\".",
ARG_LISTIDS, "List the available issue id's and exit.",
ARG_VERSION, "Output version information and exit.",
+ ARG_EXITCODE, "Set the exit code to " + ERRNO_ERRORS + " if errors are found.",
ARG_SHOW, "List available issues along with full explanations.",
ARG_SHOW + " <ids>", "Show full explanations for the given list of issue id's.",
+
"", "\nEnabled Checks:",
ARG_DISABLE + " <list>", "Disable the list of categories or " +
"specific issue id's. The list should be a comma-separated list of issue " +
@@ -823,7 +829,9 @@ public class Main extends LintClient {
ARG_CONFIG + " <filename>", "Use the given configuration file to " +
"determine whether issues are enabled or disabled. If a project contains " +
"a lint.xml file, then this config file will be used as a fallback.",
- "", "\nOutput Options:",
+
+
+ "", "\nOutput Options:",
ARG_QUIET, "Don't show progress.",
ARG_FULLPATH, "Use full paths in the error output.",
ARG_SHOWALL, "Do not truncate long messages, lists of alternate locations, etc.",
@@ -840,15 +848,14 @@ public class Main extends LintClient {
"to files, use " + ARG_URL + " " + VALUE_NONE,
ARG_SIMPLEHTML + " <filename>", "Create a simple HTML report",
ARG_XML + " <filename>", "Create an XML report instead.",
- });
- out.println("\nExit Status:");
- printUsage(out, new String[] {
- Integer.toString(ERRNO_ERRORS), "Lint errors detected.",
- Integer.toString(ERRNO_USAGE), "Lint usage.",
- Integer.toString(ERRNO_EXISTS), "Cannot clobber existing file.",
- Integer.toString(ERRNO_HELP), "Lint help.",
- Integer.toString(ERRNO_INVALIDARGS), "Invalid command-line argument.",
+ "", "\nExit Status:",
+ "0", "Success.",
+ Integer.toString(ERRNO_ERRORS), "Lint errors detected.",
+ Integer.toString(ERRNO_USAGE), "Lint usage.",
+ Integer.toString(ERRNO_EXISTS), "Cannot clobber existing file.",
+ Integer.toString(ERRNO_HELP), "Lint help.",
+ Integer.toString(ERRNO_INVALIDARGS), "Invalid command-line argument.",
});
}
@@ -936,12 +943,12 @@ public class Main extends LintClient {
}
if (severity == Severity.FATAL) {
- mFatal = true;
// From here on, treat the fatal error as an error such that we don't display
// both "Fatal:" and "Error:" etc in the error output.
severity = Severity.ERROR;
}
if (severity == Severity.ERROR) {
+ mHasErrors = true;
mErrorCount++;
} else {
mWarningCount++;
@@ -1096,11 +1103,14 @@ public class Main extends LintClient {
// Detectors shouldn't be returning ignore as a default severity,
// but in case they do, force it up to warning here to ensure that
// it's run
- if (severity == Severity.IGNORE && severity == issue.getDefaultSeverity()) {
- return Severity.WARNING;
- } else {
- return severity;
+ if (severity == Severity.IGNORE) {
+ severity = issue.getDefaultSeverity();
+ if (severity == Severity.IGNORE) {
+ severity = Severity.WARNING;
+ }
}
+
+ return severity;
}
if (mCheck != null && issue != LINT_ERROR && issue != PARSER_ERROR) {
@@ -1162,6 +1172,11 @@ public class Main extends LintClient {
return path;
}
+ /** Returns whether all warnings are enabled, including those disabled by default */
+ boolean isAllEnabled() {
+ return mWarnAll;
+ }
+
/** Returns the issue registry used by this client */
IssueRegistry getRegistry() {
return mRegistry;
diff --git a/lint/cli/src/com/android/tools/lint/MultiProjectHtmlReporter.java b/lint/cli/src/com/android/tools/lint/MultiProjectHtmlReporter.java
index db7b4fb..d039edc 100644
--- a/lint/cli/src/com/android/tools/lint/MultiProjectHtmlReporter.java
+++ b/lint/cli/src/com/android/tools/lint/MultiProjectHtmlReporter.java
@@ -37,17 +37,17 @@ import java.util.Set;
* "Multiplexing" reporter which allows output to be split up into a separate
* report for each separate project. It also adds an overview index.
*/
-class MultiProjectHtmlReporter extends HtmlReporter {
+public class MultiProjectHtmlReporter extends HtmlReporter {
private static final String INDEX_NAME = "index.html"; //$NON-NLS-1$
private final File mDir;
- MultiProjectHtmlReporter(Main client, File dir) throws IOException {
+ public MultiProjectHtmlReporter(Main client, File dir) throws IOException {
super(client, new File(dir, INDEX_NAME));
mDir = dir;
}
@Override
- void write(int errorCount, int warningCount, List<Warning> allIssues) throws IOException {
+ public void write(int errorCount, int warningCount, List<Warning> allIssues) throws IOException {
Map<Project, List<Warning>> projectToWarnings = new HashMap<Project, List<Warning>>();
for (Warning warning : allIssues) {
List<Warning> list = projectToWarnings.get(warning.project);
diff --git a/lint/cli/src/com/android/tools/lint/Reporter.java b/lint/cli/src/com/android/tools/lint/Reporter.java
index bee0eb4..2c86635 100644
--- a/lint/cli/src/com/android/tools/lint/Reporter.java
+++ b/lint/cli/src/com/android/tools/lint/Reporter.java
@@ -20,6 +20,7 @@ import static com.android.tools.lint.detector.api.LintConstants.DOT_9PNG;
import static com.android.tools.lint.detector.api.LintConstants.DOT_PNG;
import static com.android.tools.lint.detector.api.LintUtils.endsWith;
+import com.google.common.annotations.Beta;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
import com.google.common.io.Files;
@@ -35,8 +36,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-/** A reporter is an output generator for lint warnings */
-abstract class Reporter {
+/** A reporter is an output generator for lint warnings
+ * <p>
+ * <b>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.</b>
+ */
+@Beta
+public abstract class Reporter {
protected final Main mClient;
protected final File mOutput;
protected String mTitle = "Lint Report";
@@ -47,7 +53,16 @@ abstract class Reporter {
protected Map<File, String> mResourceUrl = new HashMap<File, String>();
protected Map<String, File> mNameToFile = new HashMap<String, File>();
- abstract void write(int errorCount, int warningCount, List<Warning> issues) throws IOException;
+ /**
+ * Write the given warnings into the report
+ *
+ * @param errorCount the number of errors
+ * @param warningCount the number of warnings
+ * @param issues the issues to be reported
+ * @throws IOException if an error occurs
+ */
+ public abstract void write(int errorCount, int warningCount, List<Warning> issues)
+ throws IOException;
protected Reporter(Main client, File output) {
mClient = client;
@@ -59,12 +74,12 @@ abstract class Reporter {
*
* @param title the title of the report
*/
- void setTitle(String title) {
+ public void setTitle(String title) {
mTitle = title;
}
/** @return the title of the report */
- String getTitle() {
+ public String getTitle() {
return mTitle;
}
@@ -75,7 +90,7 @@ abstract class Reporter {
* @param bundleResources if true, copy images into a directory relative to
* the report
*/
- void setBundleResources(boolean bundleResources) {
+ public void setBundleResources(boolean bundleResources) {
mBundleResources = bundleResources;
mSimpleFormat = false;
}
@@ -86,7 +101,7 @@ abstract class Reporter {
*
* @param simpleFormat whether the formatting should be simple
*/
- void setSimpleFormat(boolean simpleFormat) {
+ public void setSimpleFormat(boolean simpleFormat) {
mSimpleFormat = simpleFormat;
}
@@ -96,7 +111,7 @@ abstract class Reporter {
*
* @return whether the report should use simple formatting
*/
- boolean isSimpleFormat() {
+ public boolean isSimpleFormat() {
return mSimpleFormat;
}
diff --git a/lint/cli/src/com/android/tools/lint/TextReporter.java b/lint/cli/src/com/android/tools/lint/TextReporter.java
index 47202d1..63ee857 100644
--- a/lint/cli/src/com/android/tools/lint/TextReporter.java
+++ b/lint/cli/src/com/android/tools/lint/TextReporter.java
@@ -18,22 +18,35 @@ package com.android.tools.lint;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.Position;
+import com.google.common.annotations.Beta;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
-/** A reporter which emits lint warnings as plain text strings */
-class TextReporter extends Reporter {
+/**
+ * A reporter which emits lint warnings as plain text strings
+ * <p>
+ * <b>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.</b>
+ */
+@Beta
+public class TextReporter extends Reporter {
private final Writer mWriter;
- TextReporter(Main client, Writer writer) {
+ /**
+ * Constructs a new {@link TextReporter}
+ *
+ * @param client the client
+ * @param writer the writer to write into
+ */
+ public TextReporter(Main client, Writer writer) {
super(client, null);
mWriter = writer;
}
@Override
- void write(int errorCount, int warningCount, List<Warning> issues) throws IOException {
+ public void write(int errorCount, int warningCount, List<Warning> issues) throws IOException {
boolean abbreviate = mClient.getDriver().isAbbreviating();
StringBuilder output = new StringBuilder(issues.size() * 200);
diff --git a/lint/cli/src/com/android/tools/lint/XmlReporter.java b/lint/cli/src/com/android/tools/lint/XmlReporter.java
index 4de1dd7..03fc937 100644
--- a/lint/cli/src/com/android/tools/lint/XmlReporter.java
+++ b/lint/cli/src/com/android/tools/lint/XmlReporter.java
@@ -18,6 +18,7 @@ package com.android.tools.lint;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.Position;
+import com.google.common.annotations.Beta;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
@@ -29,17 +30,28 @@ import java.util.List;
/**
* A reporter which emits lint results into an XML report.
+ * <p>
+ * <b>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.</b>
*/
-class XmlReporter extends Reporter {
+@Beta
+public class XmlReporter extends Reporter {
private final Writer mWriter;
- XmlReporter(Main client, File output) throws IOException {
+ /**
+ * Constructs a new {@link XmlReporter}
+ *
+ * @param client the client
+ * @param output the output file
+ * @throws IOException if an error occurs
+ */
+ public XmlReporter(Main client, File output) throws IOException {
super(client, output);
mWriter = new BufferedWriter(Files.newWriter(output, Charsets.UTF_8));
}
@Override
- void write(int errorCount, int warningCount, List<Warning> issues) throws IOException {
+ public void write(int errorCount, int warningCount, List<Warning> issues) throws IOException {
mWriter.write(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //$NON-NLS-1$
"<issues>\n"); //$NON-NLS-1$
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiClass.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiClass.java
index 7223670..8c35b74 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiClass.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiClass.java
@@ -172,6 +172,17 @@ public class ApiClass {
}
public void addMethod(String name, int since) {
+ // Strip off the method type at the end to ensure that the code which
+ // produces inherited methods doesn't get confused and end up multiple entries.
+ // For example, java/nio/Buffer has the method "array()Ljava/lang/Object;",
+ // and the subclass java/nio/ByteBuffer has the method "array()[B". We want
+ // the lookup on mMethods to associate the ByteBuffer array method to be
+ // considered overriding the Buffer method.
+ int index = name.indexOf(')');
+ if (index != -1) {
+ name = name.substring(0, index + 1);
+ }
+
Integer i = mMethods.get(name);
if (i == null || i.intValue() > since) {
mMethods.put(name, Integer.valueOf(since));
@@ -204,23 +215,47 @@ public class ApiClass {
}
/**
- * Returns the set of all members (method and fields), including inherited
+ * Returns the set of all methods, including inherited
* ones.
*
* @param info the api to look up super classes from
- * @return a set containing all the members (methods and fields)
+ * @return a set containing all the members fields
*/
- public Set<String> getAllMembers(Api info) {
+ public Set<String> getAllMethods(Api info) {
Set<String> members = new HashSet<String>(100);
- addAllMembers(info, members);
+ addAllMethods(info, members);
return members;
}
- private void addAllMembers(Api info, Set<String> set) {
+ private void addAllMethods(Api info, Set<String> set) {
for (String method : mMethods.keySet()) {
set.add(method);
}
+ for (Pair<String, Integer> superClass : mSuperClasses) {
+ ApiClass clz = info.getClass(superClass.getFirst());
+ assert clz != null : superClass.getSecond();
+ if (clz != null) {
+ clz.addAllMethods(info, set);
+ }
+ }
+ }
+
+ /**
+ * Returns the set of all fields, including inherited
+ * ones.
+ *
+ * @param info the api to look up super classes from
+ * @return a set containing all the fields
+ */
+ public Set<String> getAllFields(Api info) {
+ Set<String> members = new HashSet<String>(100);
+ addAllFields(info, members);
+
+ return members;
+ }
+
+ private void addAllFields(Api info, Set<String> set) {
for (String field : mFields.keySet()) {
set.add(field);
}
@@ -228,8 +263,9 @@ public class ApiClass {
ApiClass clz = info.getClass(superClass.getFirst());
assert clz != null : superClass.getSecond();
if (clz != null) {
- clz.addAllMembers(info, set);
+ clz.addAllFields(info, set);
}
}
}
+
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiLookup.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiLookup.java
index 5f9a1e3..306e6a2 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiLookup.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiLookup.java
@@ -73,7 +73,7 @@ public class ApiLookup {
/** Relative path to the api-versions.xml database file within the Lint installation */
private static final String XML_FILE_PATH = "platform-tools/api/api-versions.xml"; //$NON-NLS-1$
private static final String FILE_HEADER = "API database used by Android lint\000";
- private static final int BINARY_FORMAT_VERSION = 1;
+ private static final int BINARY_FORMAT_VERSION = 2;
private static final boolean DEBUG_FORCE_REGENERATE_BINARY = false;
private static final boolean DEBUG_SEARCH = false;
private static final boolean WRITE_STATS = false;
@@ -336,7 +336,8 @@ public class ApiLookup {
String className = entry.getKey();
ApiClass apiClass = entry.getValue();
- Set<String> allMembers = apiClass.getAllMembers(info);
+ Set<String> allMethods = apiClass.getAllMethods(info);
+ Set<String> allFields = apiClass.getAllFields(info);
// Strip out all members that have been supported since version 1.
// This makes the database *much* leaner (down from about 4M to about
@@ -345,14 +346,27 @@ public class ApiLookup {
// requires a version *higher* than the minimum. If in the future the
// database needs to answer queries about whether a method is public
// or not, then we'd need to put this data back in.
- List<String> members = new ArrayList<String>(allMembers.size());
- for (String member : allMembers) {
- Integer since;
- if (member.indexOf('(') != -1) {
- since = apiClass.getMethod(member, info);
- } else {
- since = apiClass.getField(member, info);
+ List<String> members = new ArrayList<String>(allMethods.size() + allFields.size());
+ for (String member : allMethods) {
+ Integer since = apiClass.getMethod(member, info);
+ assert since != null : className + ':' + member;
+ if (since == null) {
+ since = 1;
+ }
+ if (since != 1) {
+ members.add(member);
}
+ }
+
+ // Strip out all members that have been supported since version 1.
+ // This makes the database *much* leaner (down from about 4M to about
+ // 1.7M), and this just fills the table with entries that ultimately
+ // don't help the API checker since it just needs to know if something
+ // requires a version *higher* than the minimum. If in the future the
+ // database needs to answer queries about whether a method is public
+ // or not, then we'd need to put this data back in.
+ for (String member : allFields) {
+ Integer since = apiClass.getField(member, info);
assert since != null : className + ':' + member;
if (since == null) {
since = 1;
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java
index 4dd7eb1..dc65f26 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java
@@ -157,6 +157,7 @@ public class InefficientWeightDetector extends LayoutDetector {
}
if (allChildrenAreLayouts) {
context.report(BASELINE_WEIGHTS,
+ element,
context.getLocation(element),
"Set android:baselineAligned=\"false\" on this element for better performance",
null);
@@ -178,6 +179,7 @@ public class InefficientWeightDetector extends LayoutDetector {
"Use a %1$s of 0dip instead of %2$s for better performance",
dimension, size);
context.report(INEFFICIENT_WEIGHT,
+ element,
context.getLocation(sizeNode != null ? sizeNode : weightChild), msg, null);
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypographyDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypographyDetector.java
index bda828d..c5a9302 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypographyDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypographyDetector.java
@@ -178,6 +178,9 @@ public class TypographyDetector extends ResourceXmlDetector {
private static final String FRACTION_MESSAGE =
"Use fraction character %1$c (%2$s) instead of %3$s ?";
+ private static final String FRACTION_MESSAGE_PATTERN =
+ "Use fraction character (.+) \\((.+)\\) instead of (.+) \\?";
+
private boolean mCheckDashes;
private boolean mCheckQuotes;
private boolean mCheckFractions;
@@ -477,6 +480,17 @@ public class TypographyDetector extends ResourceXmlDetector {
edits.add(new ReplaceEdit(endOffset, 1, "\u2019")); //$NON-NLS-1$
}
}
+ } else {
+ Matcher matcher = Pattern.compile(FRACTION_MESSAGE_PATTERN).matcher(message);
+ if (matcher.find()) {
+ // "Use fraction character %1$c (%2$s) instead of %3$s ?";
+ String replace = matcher.group(3);
+ int offset = text.indexOf(replace);
+ if (offset != -1) {
+ String replaceWith = matcher.group(2);
+ edits.add(new ReplaceEdit(offset, replace.length(), replaceWith));
+ }
+ }
}
return edits;
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/UseCompoundDrawableDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/UseCompoundDrawableDetector.java
index 8ded0e6..540a0f1 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/UseCompoundDrawableDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/UseCompoundDrawableDetector.java
@@ -17,6 +17,7 @@
package com.android.tools.lint.checks;
import static com.android.tools.lint.detector.api.LintConstants.ANDROID_URI;
+import static com.android.tools.lint.detector.api.LintConstants.ATTR_BACKGROUND;
import static com.android.tools.lint.detector.api.LintConstants.ATTR_LAYOUT_WEIGHT;
import static com.android.tools.lint.detector.api.LintConstants.IMAGE_VIEW;
import static com.android.tools.lint.detector.api.LintConstants.LINEAR_LAYOUT;
@@ -86,6 +87,12 @@ public class UseCompoundDrawableDetector extends LayoutDetector {
((second.getTagName().equals(IMAGE_VIEW) &&
first.getTagName().equals(TEXT_VIEW) &&
!second.hasAttributeNS(ANDROID_URI, ATTR_LAYOUT_WEIGHT)))) {
+ // If the layout has a background, ignore since it would disappear from
+ // the TextView
+ if (element.hasAttributeNS(ANDROID_URI, ATTR_BACKGROUND)) {
+ return;
+ }
+
context.report(ISSUE, element, context.getLocation(element),
"This tag and its children can be replaced by one <TextView/> and " +
"a compound drawable", null);
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiLookupTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiLookupTest.java
index a7c2de9..044778f 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiLookupTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiLookupTest.java
@@ -57,6 +57,11 @@ public class ApiLookupTest extends AbstractCheckTest {
assertTrue(mDb.getCallVersion("java/lang/Object", "getClass", "()") <= 1);
}
+ public void testIssue26467() {
+ assertTrue(mDb.getCallVersion("java/nio/ByteBuffer", "array", "()") <= 1);
+ assertEquals(9, mDb.getCallVersion("java/nio/Buffer", "array", "()"));
+ }
+
@Override
protected Detector getDetector() {
fail("This is not used in the ApiDatabase test");
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java
index 16aee19..6abfa71 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java
@@ -31,4 +31,11 @@ public class UseCompoundDrawableDetectorTest extends AbstractCheckTest {
"<TextView/> and a compound drawable",
lintFiles("res/layout/compound.xml"));
}
+
+ public void testCompound2() throws Exception {
+ // Ignore layouts that set a custom background
+ assertEquals(
+ "No warnings.",
+ lintFiles("res/layout/compound2.xml"));
+ }
}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/compound2.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/compound2.xml
new file mode 100644
index 0000000..24f45dc
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/compound2.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="@android:drawable/ic_dialog_alert"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>